{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"name":"python","version":"3.7.10","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"markdown","source":"# Importing Libraries","metadata":{}},{"cell_type":"code","source":"import numpy as np\nimport pandas as pd\nimport matplotlib.pyplot as plt\nimport tensorflow as tf\nimport wfdb\nimport os                                                                                                         \nimport gc\nimport scipy       \nimport sklearn\nfrom pathlib import Path\nfrom sklearn.utils import shuffle\nfrom sklearn.manifold import TSNE\nimport seaborn as sns\nfrom sklearn import preprocessing\nimport shutil\nimport math\nimport random\nfrom scipy.spatial import distance","metadata":{"execution":{"iopub.status.busy":"2021-07-14T14:19:31.476702Z","iopub.execute_input":"2021-07-14T14:19:31.477266Z","iopub.status.idle":"2021-07-14T14:19:38.456120Z","shell.execute_reply.started":"2021-07-14T14:19:31.477179Z","shell.execute_reply":"2021-07-14T14:19:38.455102Z"},"trusted":true},"execution_count":1,"outputs":[]},{"cell_type":"code","source":"try:\n    tpu = tf.distribute.cluster_resolver.TPUClusterResolver()  # TPU detection\n    print('Running on TPU ', tpu.cluster_spec().as_dict()['worker'])\nexcept ValueError:\n    raise BaseException('ERROR: Not connected to a TPU runtime; please see the previous cell in this notebook for instructions!')\n\ntf.config.experimental_connect_to_cluster(tpu)\ntf.tpu.experimental.initialize_tpu_system(tpu)\ntpu_strategy = tf.distribute.experimental.TPUStrategy(tpu)","metadata":{"execution":{"iopub.status.busy":"2021-07-14T14:19:51.750919Z","iopub.execute_input":"2021-07-14T14:19:51.751327Z","iopub.status.idle":"2021-07-14T14:19:57.553867Z","shell.execute_reply.started":"2021-07-14T14:19:51.751275Z","shell.execute_reply":"2021-07-14T14:19:57.552765Z"},"trusted":true},"execution_count":2,"outputs":[{"name":"stdout","text":"Running on TPU  ['10.0.0.2:8470']\n","output_type":"stream"}]},{"cell_type":"markdown","source":"# Dataset Creation","metadata":{}},{"cell_type":"code","source":"####### Dataset Creation  \n###### Reading Dataset\n\n##### Function to read a record from single dataset\ndef data_read_mit(filepath):\n    \n    \"\"\"\n    Function to read the the inputs from MIT-BIH Dataset\n    INPUTS:- \n    1)filepath: Path to the csv file\n    \n    OUTPUTS:-\n    1)Output_signal: Output 1D array signal \n    \"\"\"\n    return (np.array(pd.read_csv(filepath,index_col=0).iloc[:,[0]]))   \n    \n##### Function to Required Annotations from .txt files\ndef feature_extractor(txt_file_path):\n    \n    \"\"\"\n       Function to extract time series data \n       from a .txt file\n    \"\"\"\n    \n    #### Reading File\n    line_list = []\n\n    with open(txt_file_path, 'r') as reader:\n\n    # Read and print the entire file line by line\n        line = reader.readline()\n        while line != '':  # The EOF char is an empty string\n            #print(line, end='')\n            line_list.append(line)\n            line = reader.readline()\n    \n    #### Taking the Time Step Data\n    line_list = line_list[1:]\n    \n    #### Splitting the Collected Text Strings and Converting them into Floating type values\n    new_list = []\n\n    for item in line_list:\n        for idx,sub_item in enumerate(item.split()):\n            if(idx == 1):\n                new_list.append(int(sub_item))\n                break\n    \n    ### Returning the feature extracted list as numpy array\n    return np.array(new_list)\n\n###### Function to Segment Signals\n##### Constants\nFS = 500\nW_LEN = 256\nW_LEN_1_4 = 256 // 4\nW_LEN_3_4 = 3 * (256 // 4)\n\n##### Function\ndef segmentSignals(signal, r_peaks_annot, normalization=True, person_id= None, file_id=None):\n    \n    \"\"\"\n    Segments signals based on the detected R-Peak\n    Args:\n        signal (numpy array): input signal\n        r_peaks_annot (int []): r-peak locations.\n        normalization (bool, optional): apply z-normalization or not? . Defaults to True.\n        person_id ([type], optional): [description]. Defaults to None.\n        file_id ([type], optional): [description]. Defaults to None.\n    Returns:\n            [tuple(numpy array,numpy array)]: segmented signals and refined r-peaks\n    \"\"\"\n    def refine_rpeaks(signal, r_peaks):\n        \"\"\"\n        Refines the detected R-peaks. If the R-peak is slightly shifted, this assigns the \n        highest point R-peak.\n        Args:\n            signal (numpy array): input signal\n            r_peaks (int []): list of detected r-peaks\n        Returns:\n            [numpy array]: refined r-peaks\n        \"\"\"\n\n        r_peaks2 = np.array(r_peaks)            # make a copy\n        for i in range(len(r_peaks)):\n            r = r_peaks[i]          # current R-peak\n            small_segment = signal[max(0,r-100):min(len(signal),r+100)]         # consider the neighboring segment of R-peak\n            r_peaks2[i] = np.argmax(small_segment) - 100 + r_peaks[i]           # picking the highest point\n            r_peaks2[i] = min(r_peaks2[i],len(signal))                          # the detected R-peak shouldn't be outside the signal\n            r_peaks2[i] = max(r_peaks2[i],0)                                    # checking if it goes before zero    \n        return r_peaks2                     # returning the refined r-peak list\n    \n    segmented_signals = []                      # array containing the segmented beats\n    \n    r_peaks = np.array(r_peaks_annot)\n    r_peaks = refine_rpeaks(signal, r_peaks)\n    skip_len = 5 # Parameter to specify number of r_peaks in one signal\n    max_seq_len = 1280 # Parameter to specify maximum sequence length\n    \n    for r_curr in range(0,int(r_peaks.shape[0]-(skip_len-1)),skip_len):\n        if ((r_peaks[r_curr]-W_LEN_1_4)<0) or ((r_peaks[r_curr+(skip_len-1)]+W_LEN_3_4)>=len(signal)):           # not enough signal to segment\n            continue\n        segmented_signal = np.array(signal[r_peaks[r_curr]-W_LEN_1_4:r_peaks[r_curr+(skip_len-1)]+W_LEN_3_4])        # segmenting a heartbeat\n        segmented_signal = list(segmented_signal)\n        #print(segmented_signal.shape)\n        \n        if(len(segmented_signal) < 1280):\n            for m in range(int(1280-len(segmented_signal))): # Zero Padding\n                segmented_signal.append(0)\n        else:\n            segmented_signal = (segmented_signal[:int(max_seq_len)])\n            \n        segmented_signal = np.array(segmented_signal)\n        \n        if(segmented_signal.shape != (1280,1)):    \n            segmented_signal = np.reshape(segmented_signal,(1280,1))\n            \n        if (normalization):             # Z-score normalization\n            if abs(np.std(segmented_signal))<1e-6:          # flat line ECG, will cause zero division error\n                continue\n            segmented_signal = (segmented_signal - np.mean(segmented_signal)) / np.std(segmented_signal)            \n              \n        #if not np.isnan(segmented_signal).any():                    # checking for nan, this will never happen\n            segmented_signals.append(segmented_signal)\n\n    return segmented_signals,r_peaks           # returning the segmented signals and the refined r-peaks","metadata":{"execution":{"iopub.status.busy":"2021-07-14T14:20:06.716758Z","iopub.execute_input":"2021-07-14T14:20:06.717116Z","iopub.status.idle":"2021-07-14T14:20:06.739172Z","shell.execute_reply.started":"2021-07-14T14:20:06.717085Z","shell.execute_reply":"2021-07-14T14:20:06.737879Z"},"trusted":true},"execution_count":4,"outputs":[]},{"cell_type":"code","source":"###### Test\nmit_dbs_path = '../input/mitbih-database'\nlist_seg_sig = []\nfor i in range(0,96,2): # Loop over all the files\n    print(i)\n    rec_file_path = os.path.join(mit_dbs_path,str(np.sort(os.listdir(mit_dbs_path))[i])) # Path Selection\n    attr_file_path = os.path.join(mit_dbs_path,str(np.sort(os.listdir(mit_dbs_path))[i+1])) # Path Selction \n    rec_file = data_read_mit(rec_file_path)\n    r_peaks = feature_extractor(attr_file_path)\n    \n    seg_sig,r_peak = segmentSignals(rec_file,list(r_peaks))\n    #seg_sig = np.array(seg_sig)\n    \n    for seg_sig_curr in seg_sig:\n        #print(np.array(seg_sig_curr).shape)\n        list_seg_sig.append(seg_sig_curr)\n        \nfor i in range(10):\n    plt.plot(np.arange(1280),list_seg_sig[i])\n    plt.show()","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"###### Looping for Reading the Entire Dataset - Training OpenSet Model\n\n! mkdir './5_Beat_Ecg_MITBIH' # Generating major database of datasets\ncurrent_index = 1\n\nmit_dbs_path = '../input/mitbih-database'\nfor i in range(0,76,2): # Loop over all the files\n    print(i)\n    print(np.sort(os.listdir(mit_dbs_path))[i])\n    rec_file_path = os.path.join(mit_dbs_path,str(np.sort(os.listdir(mit_dbs_path))[i])) # Path Selection\n    attr_file_path = os.path.join(mit_dbs_path,str(np.sort(os.listdir(mit_dbs_path))[i+1])) # Path Selction\n    \n    signal_current = data_read_mit(rec_file_path) # Current ECG Signal\n    r_peaks_current = feature_extractor(attr_file_path) # R-peaks\n    seg_signal_current,new_r_peaks = (segmentSignals(signal_current,list(r_peaks_current))) # Segmented ECG Signals\n    #seg_signal_current = np.array(seg_signal_current)\n    #print(seg_signal_current.shape[0])\n    \n    if(i == 48):\n        current_index = current_index-1\n        current_storage_path = './5_Beat_Ecg_MITBIH'+'/person'+str(current_index)\n        #Path(current_storage_path).mkdir(parents=True, exist_ok=True)\n    \n        for j in range(len(seg_signal_current)):\n            file_name_current = current_storage_path+'/Extra'+str(j)\n            np.savez_compressed(file_name_current,seg_signal_current[j])\n            \n        current_index = current_index+1\n    \n    else:\n        current_storage_path = './5_Beat_Ecg_MITBIH'+'/person'+str(current_index)\n        Path(current_storage_path).mkdir(parents=True, exist_ok=True)\n    \n        for j in range(len(seg_signal_current)):\n            file_name_current = current_storage_path+'/'+str(j)\n            np.savez_compressed(file_name_current,seg_signal_current[j])\n            \n        current_index = current_index+1","metadata":{"execution":{"iopub.status.busy":"2021-07-14T14:20:12.857318Z","iopub.execute_input":"2021-07-14T14:20:12.857702Z","iopub.status.idle":"2021-07-14T14:23:59.233870Z","shell.execute_reply.started":"2021-07-14T14:20:12.857666Z","shell.execute_reply":"2021-07-14T14:23:59.232704Z"},"trusted":true},"execution_count":5,"outputs":[{"name":"stdout","text":"mkdir: cannot create directory ‘./5_Beat_Ecg_MITBIH’: File exists\n0\n100.csv\n","output_type":"stream"},{"name":"stderr","text":"/opt/conda/lib/python3.7/site-packages/ipykernel_launcher.py:113: VisibleDeprecationWarning: Creating an ndarray from ragged nested sequences (which is a list-or-tuple of lists-or-tuples-or ndarrays with different lengths or shapes) is deprecated. If you meant to do this, you must specify 'dtype=object' when creating the ndarray\n","output_type":"stream"},{"name":"stdout","text":"2\n101.csv\n4\n102.csv\n6\n103.csv\n8\n104.csv\n10\n105.csv\n12\n106.csv\n14\n107.csv\n16\n108.csv\n18\n109.csv\n20\n111.csv\n22\n112.csv\n24\n113.csv\n26\n114.csv\n28\n115.csv\n30\n116.csv\n32\n117.csv\n34\n118.csv\n36\n119.csv\n38\n121.csv\n40\n122.csv\n42\n123.csv\n44\n124.csv\n46\n200.csv\n48\n201.csv\n50\n202.csv\n52\n203.csv\n54\n205.csv\n56\n207.csv\n58\n208.csv\n60\n209.csv\n62\n210.csv\n64\n212.csv\n66\n213.csv\n68\n214.csv\n70\n215.csv\n72\n217.csv\n74\n219.csv\n","output_type":"stream"}]},{"cell_type":"code","source":"###### Looping for Reading the Entire Dataset - OpenSet Testing\n\n! mkdir './5_Beat_Ecg_MITBIH_1' # Generating major database of datasets\ncurrent_index = 1\n\nmit_dbs_path = '../input/mitbih-database'\nfor i in range(76,96,2): # Loop over all the files\n    print(i)\n    print(np.sort(os.listdir(mit_dbs_path))[i])\n    rec_file_path = os.path.join(mit_dbs_path,str(np.sort(os.listdir(mit_dbs_path))[i])) # Path Selection\n    attr_file_path = os.path.join(mit_dbs_path,str(np.sort(os.listdir(mit_dbs_path))[i+1])) # Path Selction\n    \n    signal_current = data_read_mit(rec_file_path) # Current ECG Signal\n    r_peaks_current = feature_extractor(attr_file_path) # R-peaks\n    seg_signal_current,new_r_peaks = (segmentSignals(signal_current,list(r_peaks_current))) # Segmented ECG Signals\n    #seg_signal_current = np.array(seg_signal_current)\n    #print(seg_signal_current.shape[0])\n    \n    if(i == 48):\n        current_index = current_index-1\n        current_storage_path = './5_Beat_Ecg_MITBIH_1'+'/person'+str(current_index)\n        #Path(current_storage_path).mkdir(parents=True, exist_ok=True)\n    \n        for j in range(len(seg_signal_current)):\n            file_name_current = current_storage_path+'/Extra'+str(j)\n            np.savez_compressed(file_name_current,seg_signal_current[j])\n            \n        current_index = current_index+1\n    \n    else:\n        current_storage_path = './5_Beat_Ecg_MITBIH_1'+'/person'+str(current_index)\n        Path(current_storage_path).mkdir(parents=True, exist_ok=True)\n    \n        for j in range(len(seg_signal_current)):\n            file_name_current = current_storage_path+'/'+str(j)\n            np.savez_compressed(file_name_current,seg_signal_current[j])\n            \n        current_index = current_index+1","metadata":{"execution":{"iopub.status.busy":"2021-07-14T15:14:47.365354Z","iopub.execute_input":"2021-07-14T15:14:47.365807Z","iopub.status.idle":"2021-07-14T15:16:06.132014Z","shell.execute_reply.started":"2021-07-14T15:14:47.365771Z","shell.execute_reply":"2021-07-14T15:16:06.130725Z"},"trusted":true},"execution_count":16,"outputs":[{"name":"stdout","text":"76\n220.csv\n","output_type":"stream"},{"name":"stderr","text":"/opt/conda/lib/python3.7/site-packages/ipykernel_launcher.py:113: VisibleDeprecationWarning: Creating an ndarray from ragged nested sequences (which is a list-or-tuple of lists-or-tuples-or ndarrays with different lengths or shapes) is deprecated. If you meant to do this, you must specify 'dtype=object' when creating the ndarray\n","output_type":"stream"},{"name":"stdout","text":"78\n221.csv\n80\n222.csv\n82\n223.csv\n84\n228.csv\n86\n230.csv\n88\n231.csv\n90\n232.csv\n92\n233.csv\n94\n234.csv\n","output_type":"stream"}]},{"cell_type":"code","source":"###### Creation of Numpy Arrays\n##### Defining Essentials\ndata_folder = './5_Beat_Ecg_MITBIH_1'\nX_train = []\nX_dev = []\ny_train = []     \ny_dev = []\n\n##### Looping Over to populate the dataset\nfor index,sub_data_folder in enumerate(np.sort(os.listdir(data_folder))):\n    sub_data_folder_path = os.path.join(data_folder,sub_data_folder)\n    \n    #if(index <= 33):\n        \n    for idx,item in enumerate(np.sort(os.listdir(sub_data_folder_path))): # Looping Over a person's folder\n        item_path = os.path.join(sub_data_folder_path,item)\n\n        #### Train on Past Test on Present (TPTP)\n        if(idx <= int(np.round(len(os.listdir(sub_data_folder_path))*0.7))):\n            X_train.append(np.load(item_path,allow_pickle=True)['arr_0'])\n            y_train.append(index)\n        else:\n            X_dev.append(np.load(item_path,allow_pickle=True)['arr_0'])\n            y_dev.append(index)\n            \n    print('Person'+' '+str(index+1)+'s data taken')\n    \n        #### Alternate Training Strategy (ALT)\n        #if(idx%2 == 0 and  idx != 1):\n        #    X_train.append(np.load(item_path,allow_pickle=True)['arr_0'])\n        #    y_train.append(index-35)\n        #else:\n        #    X_dev.append(np.load(item_path,allow_pickle=True)['arr_0'])\n        #    y_dev.append(index-35)\n\n    #### Random Training Strategy (RAND)\n    #dir_sub = list(np.sort(os.listdir(sub_data_folder_path)))\n    #dir_shuffled = shuffle(dir_sub)\n    #print(dir_shuffled)\n    \n    #for idx,item in enumerate(dir_shuffled): # Looping Over a person's folder\n    #    item_path = os.path.join(sub_data_folder_path,item)\n\n    #    if(idx <= int(len(dir_shuffled)//2)):\n    #        X_train.append(np.load(item_path,allow_pickle=True)['arr_0'])\n    #        y_train.append(index)\n    #    else:\n    #        X_dev.append(np.load(item_path,allow_pickle=True)['arr_0'])\n    #        y_dev.append(index)    \n        \n    #print('Person'+' '+str(index+1)+'s data taken')\n            \n##### Creation of Numpy Arrays\nX_train = np.array(X_train)\nX_dev = np.array(X_dev)\ny_train = np.array(y_train)\ny_dev = np.array(y_dev)\n\n##### Shuffling Dataset\nX_train,y_train = shuffle(X_train,y_train,random_state=23)\nX_dev,y_dev = shuffle(X_dev,y_dev,random_state=23)\n\n##### Saving Dataset\nnp.savez_compressed('./X_train_OSV_Test_MITBIH.npz',X_train)\nnp.savez_compressed('./X_dev_OSV_Test_MITBIH.npz',X_dev)\nnp.savez_compressed('./y_train_OSV_Test_MITBIH.npz',y_train)\nnp.savez_compressed('./y_dev_OSV_Test_MITBIH.npz',y_dev)","metadata":{"execution":{"iopub.status.busy":"2021-07-14T15:27:53.450566Z","iopub.execute_input":"2021-07-14T15:27:53.451029Z","iopub.status.idle":"2021-07-14T15:28:41.576148Z","shell.execute_reply.started":"2021-07-14T15:27:53.450991Z","shell.execute_reply":"2021-07-14T15:28:41.575054Z"},"trusted":true},"execution_count":17,"outputs":[{"name":"stdout","text":"Person 1s data taken\nPerson 2s data taken\nPerson 3s data taken\nPerson 4s data taken\nPerson 5s data taken\nPerson 6s data taken\nPerson 7s data taken\nPerson 8s data taken\nPerson 9s data taken\nPerson 10s data taken\n","output_type":"stream"}]},{"cell_type":"code","source":"##### Loading Dataset - ALT  \n#X_train = np.array(np.load('../input/5beat-ecg-identification-mitbih/X_train.npz',allow_pickle=True)['arr_0'],dtype=np.float16)\n#X_dev = np.array(np.load('../input/5beat-ecg-identification-mitbih/X_dev.npz',allow_pickle=True)['arr_0'],dtype=np.float16)\n#y_train = np.load('../input/5beat-ecg-identification-mitbih/y_train.npz',allow_pickle=True)['arr_0']\n#y_dev = np.load('../input/5beat-ecg-identification-mitbih/y_dev.npz',allow_pickle=True)['arr_0']\n\n##### Loading Dataset - TPTP\n#X_train = np.array(np.load('./X_train_Verification_MITBIH.npz',allow_pickle=True)['arr_0'],dtype=np.float16)\n#X_dev = np.array(np.load('./X_dev_Verification_MITBIH.npz',allow_pickle=True)['arr_0'],dtype=np.float16)\n#y_train = np.load('./y_train_Verification_MITBIH.npz',allow_pickle=True)['arr_0']\n#y_dev = np.load('./y_dev_Verification_MITBIH.npz',allow_pickle=True)['arr_0']\n                            \n##### Loading Dataset -  OSV_Train                                           \n#X_train = np.array(np.load('./X_train_OSV_Train_MITBIH.npz',allow_pickle=True)['arr_0'],dtype=np.float16)\n#X_dev = np.array(np.load('./X_dev_OSV_Train_MITBIH.npz',allow_pickle=True)['arr_0'],dtype=np.float16)\n#y_train = np.load('./y_train_OSV_Train_MITBIH.npz',allow_pickle=True)['arr_0']\n#y_dev = np.load('./y_dev_OSV_Train_MITBIH.npz',allow_pickle=True)['arr_0']    \n     \n##### Loading Dataset - OSV_Test                                                   \nX_train = np.array(np.load('./X_train_OSV_Test_MITBIH.npz',allow_pickle=True)['arr_0'],dtype=np.float16)\nX_dev = np.array(np.load('./X_dev_OSV_Test_MITBIH.npz',allow_pickle=True)['arr_0'],dtype=np.float16)\ny_train = np.load('./y_train_OSV_Test_MITBIH.npz',allow_pickle=True)['arr_0']\ny_dev = np.load('./y_dev_OSV_Test_MITBIH.npz',allow_pickle=True)['arr_0']\n\n##### Loading Dataset - RAND\n#X_train = np.array(np.load('./X_train_RAND_MITBIH.npz',allow_pickle=True)['arr_0'],dtype=np.float16)\n#X_dev = np.array(np.load('./X_dev_RAND_MITBIH.npz',allow_pickle=True)['arr_0'],dtype=np.float16)\n#y_train = np.load('./y_train_RAND_MITBIH.npz',allow_pickle=True)['arr_0']\n#y_dev = np.load('./y_dev_RAND_MITBIH.npz',allow_pickle=True)['arr_0']","metadata":{"execution":{"iopub.status.busy":"2021-07-14T15:32:01.661561Z","iopub.execute_input":"2021-07-14T15:32:01.662030Z","iopub.status.idle":"2021-07-14T15:32:15.594021Z","shell.execute_reply.started":"2021-07-14T15:32:01.661988Z","shell.execute_reply":"2021-07-14T15:32:15.593085Z"},"trusted":true},"execution_count":18,"outputs":[]},{"cell_type":"code","source":"##### Converting Labels to Categorical Format\ny_train_ohot = tf.keras.utils.to_categorical(y_train)\ny_dev_ohot = tf.keras.utils.to_categorical(y_dev)","metadata":{"execution":{"iopub.status.busy":"2021-07-14T15:32:46.814729Z","iopub.execute_input":"2021-07-14T15:32:46.815138Z","iopub.status.idle":"2021-07-14T15:32:46.821347Z","shell.execute_reply.started":"2021-07-14T15:32:46.815095Z","shell.execute_reply":"2021-07-14T15:32:46.820028Z"},"trusted":true},"execution_count":19,"outputs":[]},{"cell_type":"code","source":"##### Testing Dataset Validity\nfor i in range(10):\n    \n    if(y_dev[i]==1):\n    #### Training Set\n        plt.plot(np.arange(0,1280),X_dev[i])\n        plt.show()\n        print('Class of the ECG:-'+' '+str(y_dev[i]))\n\n        #### Dev Set\n        #plt.plot(np.arange(0,256),X_dev[i])\n        #plt.show()\n        #print('Class of the ECG:-'+' '+str(y_dev[i]))","metadata":{"execution":{"iopub.status.busy":"2021-06-08T06:50:11.600255Z","iopub.execute_input":"2021-06-08T06:50:11.600666Z","iopub.status.idle":"2021-06-08T06:50:11.605712Z","shell.execute_reply.started":"2021-06-08T06:50:11.600628Z","shell.execute_reply":"2021-06-08T06:50:11.604932Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Model Making","metadata":{}},{"cell_type":"markdown","source":"## Self-Calibrated Convolutions","metadata":{}},{"cell_type":"code","source":"###### Model Development : Self-Calibrated \n\n##### Defining Self-Calibrated Block\n\nrate_regularizer = 1e-5\nclass self_cal_Conv1D(tf.keras.layers.Layer):\n\n    \"\"\" \n    This is inherited class from keras.layers and shall be instatition of self-calibrated convolutions\n    \"\"\"\n    \n    def __init__(self,num_filters,kernel_size,num_features):\n    \n        #### Defining Essentials\n        super().__init__()\n        self.num_filters = num_filters\n        self.kernel_size = kernel_size\n        self.num_features = num_features # Number of Channels in Input\n\n        #### Defining Layers\n        self.conv2 = tf.keras.layers.Conv1D(self.num_features/2,self.kernel_size,padding='same',kernel_regularizer=tf.keras.regularizers.l2(rate_regularizer),dtype='float32',activation='relu')\n        self.conv3 = tf.keras.layers.Conv1D(self.num_features/2,self.kernel_size,padding='same',kernel_regularizer=tf.keras.regularizers.l2(rate_regularizer),dtype='float32',activation='relu')\n        self.conv4 = tf.keras.layers.Conv1D(self.num_filters/2,self.kernel_size,padding='same',activation='relu',kernel_regularizer=tf.keras.regularizers.l2(rate_regularizer),dtype='float32')\n        self.conv1 = tf.keras.layers.Conv1D(self.num_filters/2,self.kernel_size,padding='same',activation='relu',kernel_regularizer=tf.keras.regularizers.l2(rate_regularizer),dtype='float32')\n        self.upsample = tf.keras.layers.Conv1DTranspose(filters=int(self.num_features/2),kernel_size=5,strides=5)\n        #self.attention_layer = tf.keras.layers.Attention()\n        #self.lstm = tf.keras.layers.LSTM(int(self.num_features/2),return_sequences=True)\n        #self.layernorm = tf.keras.layers.LayerNormalization()\n    \n    def get_config(self):\n\n        config = super().get_config().copy()\n        config.update({\n            'num_filters': self.num_filters,\n            'kernel_size': self.kernel_size,\n            'num_features': self.num_features\n        })\n        return config\n    \n    \n    def call(self,X):\n       \n        \"\"\"\n          INPUTS : 1) X - Input Tensor of shape (batch_size,sequence_length,num_features)\n          OUTPUTS : 1) X - Output Tensor of shape (batch_size,sequence_length,num_features)\n        \"\"\"\n        \n        #### Dimension Extraction\n        b_s = (X.shape)[0] \n        seq_len = (X.shape)[1]\n        num_features = (X.shape)[2]\n        \n        #### Channel-Wise Division\n        X_attention = X[:,:,0:int(self.num_features/2)]\n        X_global = X[:,:,int(self.num_features/2):]\n        \n        #### Self Calibration Block\n\n        ### Local Feature Detection\n\n        ## Down-Sampling\n        #x1 = X_attention[:,0:int(seq_len/5),:]\n        #x2 = X_attention[:,int(seq_len/5):int(seq_len*(2/5)),:]\n        #x3 = X_attention[:,int(seq_len*(2/5)):int(seq_len*(3/5)),:]\n        #x4 = X_attention[:,int(seq_len*(3/5)):int(seq_len*(4/5)),:]\n        #x5 = X_attention[:,int(seq_len*(4/5)):seq_len,:]\n        x_down_sampled = tf.keras.layers.AveragePooling1D(pool_size=5,strides=5)(X_attention)\n        \n        ## Convoluting Down Sampled Sequence \n        #x1 = self.conv2(x1)\n        #x2 = self.conv2(x2)\n        #x3 = self.conv2(x3)\n        #x4 = self.conv2(x4)\n        #x5 = self.conv2(x5)\n        x_down_conv = self.conv2(x_down_sampled)\n        #x_down_feature = self.attention_layer([x_down_sampled,x_down_sampled])\n        #x_down_feature = self.lstm(x_down_sampled)\n        #x_down_feature = self.layernorm(x_down_feature)\n        \n        ## Up-Sampling\n        x_down_upsampled = self.upsample(x_down_conv)   \n        #X_local_upsampled = tf.keras.layers.concatenate([x1,x2,x3,x4,x5],axis=1)\n\n        ## Local-CAM\n        X_local = X_attention + x_down_upsampled  #X_local_upsampled\n\n        ## Local Importance \n        X_2 = tf.keras.activations.sigmoid(X_local)\n\n        ### Self-Calibration\n\n        ## Global Convolution\n        X_3 = self.conv3(X_attention)\n\n        ## Attention Determination\n        X_attention = tf.math.multiply(X_2,X_3)\n\n        #### Self-Calibration Feature Extraction\n        X_4 = self.conv4(X_attention)\n\n        #### Normal Feature Extraction\n        X_1 = self.conv1(X_global)\n\n        #### Concatenating and Returning Output\n        return (tf.keras.layers.concatenate([X_1,X_4],axis=2))","metadata":{"execution":{"iopub.status.busy":"2021-07-14T14:33:44.891499Z","iopub.execute_input":"2021-07-14T14:33:44.891854Z","iopub.status.idle":"2021-07-14T14:33:44.912245Z","shell.execute_reply.started":"2021-07-14T14:33:44.891825Z","shell.execute_reply":"2021-07-14T14:33:44.910788Z"},"trusted":true},"execution_count":9,"outputs":[]},{"cell_type":"markdown","source":"# Transformer","metadata":{}},{"cell_type":"code","source":"def get_angles(pos, i, d_model):\n    angle_rates = 1 / np.power(10000, (2 * (i//2)) / np.float32(d_model))\n    return pos * angle_rates\n\ndef positional_encoding(position, d_model):\n    angle_rads = get_angles(np.arange(position)[:, np.newaxis],\n                          np.arange(d_model)[np.newaxis, :],\n                          d_model)\n  \n  # apply sin to even indices in the array; 2i\n    angle_rads[:, 0::2] = np.sin(angle_rads[:, 0::2])\n  \n  # apply cos to odd indices in the array; 2i+1\n    angle_rads[:, 1::2] = np.cos(angle_rads[:, 1::2])\n    \n    pos_encoding = angle_rads[np.newaxis, ...]\n    \n    return tf.cast(pos_encoding, dtype=tf.float32)\n\ndef create_padding_mask(seq):\n    seq = tf.cast(tf.math.equal(seq, 0), tf.float32)\n  \n    # add extra dimensions to add the padding\n    # to the attention logits. \n    return seq[:, tf.newaxis, tf.newaxis, :]  # (batch_size, 1, 1, seq_len)\n\ndef scaled_dot_product_attention(q, k, v, mask):\n    \"\"\"Calculate the attention weights.\n    q, k, v must have matching leading dimensions.\n    k, v must have matching penultimate dimension, i.e.: seq_len_k = seq_len_v.\n    The mask has different shapes depending on its type(padding or look ahead) \n    but it must be broadcastable for addition.\n\n    Args:\n    q: query shape == (..., seq_len_q, depth)\n    k: key shape == (..., seq_len_k, depth)\n    v: value shape == (..., seq_len_v, depth_v)\n    mask: Float tensor with shape broadcastable \n          to (..., seq_len_q, seq_len_k). Defaults to None.\n\n    Returns:\n    output, attention_weights\n    \"\"\"\n\n    matmul_qk = tf.matmul(q, k, transpose_b=True)  # (..., seq_len_q, seq_len_k)\n  \n    # scale matmul_qk\n    dk = tf.cast(tf.shape(k)[-1], tf.float32)\n    scaled_attention_logits = matmul_qk / tf.math.sqrt(dk)\n\n    # add the mask to the scaled tensor.\n    if mask is not None:\n        scaled_attention_logits += (mask * -1e9)  \n\n    # softmax is normalized on the last axis (seq_len_k) so that the scores\n    # add up to 1.\n    attention_weights = tf.nn.softmax(scaled_attention_logits, axis=-1)  # (..., seq_len_q, seq_len_k)\n\n    output = tf.matmul(attention_weights, v)  # (..., seq_len_q, depth_v)\n\n    return output, attention_weights\n\nclass MultiHeadAttention(tf.keras.layers.Layer):\n    def __init__(self, d_model, num_heads):\n        super(MultiHeadAttention, self).__init__()\n        self.num_heads = num_heads\n        self.d_model = d_model\n\n        assert d_model % self.num_heads == 0\n\n        self.depth = d_model // self.num_heads\n\n        self.wq = tf.keras.layers.Dense(d_model)\n        self.wk = tf.keras.layers.Dense(d_model)\n        self.wv = tf.keras.layers.Dense(d_model)\n\n        self.dense = tf.keras.layers.Dense(d_model)\n\n    def get_config(self):\n        config = super(MultiHeadAttention, self).get_config().copy()\n        config.update({\n            'd_model': self.d_model,\n            'num_heads':self.num_heads\n        })\n        \n    def split_heads(self, x, batch_size):\n        \n        \"\"\"Split the last dimension into (num_heads, depth).\n        Transpose the result such that the shape is (batch_size, num_heads, seq_len, depth)\n        \"\"\"\n        x = tf.reshape(x, (batch_size, -1, self.num_heads, self.depth))\n        return tf.transpose(x, perm=[0, 2, 1, 3])\n    \n    def call(self, v, k, q, mask):\n        batch_size = tf.shape(q)[0]\n\n        q = self.wq(q)  # (batch_size, seq_len, d_model)\n        k = self.wk(k)  # (batch_size, seq_len, d_model)\n        v = self.wv(v)  # (batch_size, seq_len, d_model)\n\n        q = self.split_heads(q, batch_size)  # (batch_size, num_heads, seq_len_q, depth)\n        k = self.split_heads(k, batch_size)  # (batch_size, num_heads, seq_len_k, depth)\n        v = self.split_heads(v, batch_size)  # (batch_size, num_heads, seq_len_v, depth)\n\n        # scaled_attention.shape == (batch_size, num_heads, seq_len_q, depth)\n        # attention_weights.shape == (batch_size, num_heads, seq_len_q, seq_len_k)\n        scaled_attention, attention_weights = scaled_dot_product_attention(\n            q, k, v, mask)\n\n        scaled_attention = tf.transpose(scaled_attention, perm=[0, 2, 1, 3])  # (batch_size, seq_len_q, num_heads, depth)\n\n        concat_attention = tf.reshape(scaled_attention, \n                                      (batch_size, -1, self.d_model))  # (batch_size, seq_len_q, d_model)\n\n        output = self.dense(concat_attention)  # (batch_size, seq_len_q, d_model)\n\n        return output, attention_weights\n\ndef point_wise_feed_forward_network(d_model, dff):\n    return tf.keras.Sequential([\n      tf.keras.layers.Dense(dff, activation='relu'),  # (batch_size, seq_len, dff)\n      tf.keras.layers.Dense(d_model)  # (batch_size, seq_len, d_model)\n  ])\n\nclass Encoder(tf.keras.layers.Layer):\n    def __init__(self, num_layers, d_model, num_heads, dff,\n               maximum_position_encoding, rate=0.1):\n        super(Encoder, self).__init__()\n\n        self.d_model = d_model\n        self.num_layers = num_layers\n        self.num_heads = num_heads\n        self.dff = dff\n        self.maximum_position_encoding = maximum_position_encoding\n        self.rate = rate\n\n        #self.embedding = tf.keras.layers.Embedding(input_vocab_size, d_model)\n        self.pos_encoding = positional_encoding(maximum_position_encoding, \n                                                self.d_model)\n\n\n        self.enc_layers = [EncoderLayer(d_model, num_heads, dff, rate) \n                           for _ in range(num_layers)]\n\n        self.dropout = tf.keras.layers.Dropout(rate)\n        \n    def get_config(self):\n        config = super(Encoder, self).get_config().copy()\n        config.update({\n            'num_layers': self.num_layers,\n            'd_model': self.d_model,\n            'num_heads':self.num_heads,\n            'dff':self.dff,\n            'maximum_position_encoding':self.maximum_position_encoding,\n            'rate':self.rate  \n        })\n        \n    def call(self, x, training, mask):\n\n        seq_len = tf.shape(x)[1]\n\n        # adding embedding and position encoding.\n        #x = self.embedding(x)  # (batch_size, input_seq_len, d_model)\n        x *= tf.math.sqrt(tf.cast(self.d_model, tf.float32))\n        x += self.pos_encoding[:, :seq_len, :]\n\n        x = self.dropout(x, training=training)         \n\n        for i in range(self.num_layers):\n            x = self.enc_layers[i](x, training, mask)\n\n        return x  # (batch_size, input_seq_len, d_model)\n\nclass EncoderLayer(tf.keras.layers.Layer):\n    def __init__(self, d_model, num_heads, dff, rate=0.1):\n        super(EncoderLayer, self).__init__()\n        \n        self.d_model = d_model\n        self.num_heads = num_heads\n        self.dff = dff\n        self.rate = rate\n\n        self.mha = MultiHeadAttention(d_model, num_heads)\n        self.ffn = point_wise_feed_forward_network(d_model, dff)\n\n        self.layernorm1 = tf.keras.layers.LayerNormalization(epsilon=1e-6)\n        self.layernorm2 = tf.keras.layers.LayerNormalization(epsilon=1e-6)\n\n        self.dropout1 = tf.keras.layers.Dropout(rate)\n        self.dropout2 = tf.keras.layers.Dropout(rate)\n        \n    def get_config(self):\n        config = super(EncoderLayer, self).get_config().copy()\n        config.update({\n            'd_model': self.d_model,\n            'num_heads':self.num_heads,\n            'dff':self.dff,\n            'rate':self.rate  \n        })\n\n    def call(self, x, training, mask):\n\n        attn_output, _ = self.mha(x, x, x, mask)  # (batch_size, input_seq_len, d_model)\n        attn_output = self.dropout1(attn_output, training=training)\n        out1 = self.layernorm1(x + attn_output)  # (batch_size, input_seq_len, d_model)\n\n        ffn_output = self.ffn(out1)  # (batch_size, input_seq_len, d_model)\n        ffn_output = self.dropout2(ffn_output, training=training)\n        out2 = self.layernorm2(out1 + ffn_output)  # (batch_size, input_seq_len, d_model)\n    \n        return out2\n    \nclass Transformer(tf.keras.Model):\n    def __init__(self, num_layers, d_model, num_heads, dff, \n                 pe_input, rate=0.1):\n        super(Transformer, self).__init__()\n        \n        self.num_layers = num_layers\n        self.d_model = d_model\n        self.num_heads = num_heads\n        self.dff = dff\n        self.pe_input = pe_input\n        self.rate = rate\n        \n        self.encoder = Encoder(num_layers, d_model, num_heads, dff, \n                                pe_input, rate)\n        \n    def get_config(self):\n        config = super(Transformer,self).get_config().copy()\n        config.update({\n            'num_layers': self.num_layers,\n            'd_model': self.d_model,\n            'num_heads':self.num_heads,\n            'dff':self.dff,\n            'pe_input':self.pe_input,\n            'rate':self.rate  \n        })\n    \n    def call(self, inp, training, enc_padding_mask):\n        return self.encoder(inp, training, enc_padding_mask)","metadata":{"execution":{"iopub.status.busy":"2021-07-14T14:33:50.436487Z","iopub.execute_input":"2021-07-14T14:33:50.436897Z","iopub.status.idle":"2021-07-14T14:33:50.485919Z","shell.execute_reply.started":"2021-07-14T14:33:50.436864Z","shell.execute_reply":"2021-07-14T14:33:50.484901Z"},"trusted":true},"execution_count":10,"outputs":[]},{"cell_type":"markdown","source":"## ArcFace Loss","metadata":{}},{"cell_type":"code","source":"###### ArcFace Layer\n\n##### Layer \nclass ArcFace(tf.keras.layers.Layer):\n\n    \"\"\" ArcFace Logits Generation Layer \"\"\"\n\n    def __init__(self,num_classes,s,m,input_embedding_dims):\n\n        #### Defining Essentials\n        super().__init__()\n        self.num_classes = num_classes # Number of Classes in the Outut\n        self.s = s # Geodesic Scaled Distance\n        self.m = m # Additive Angular Margin\n        self.input_embedding_dims = input_embedding_dims # Dimesnsion of Input to the ArcFace Layer\n\n        #### Defining Weight\n        self.W = self.add_weight(shape=(self.input_embedding_dims, self.num_classes),\n                                initializer='glorot_uniform',\n                                trainable=True,\n                                )\n\n    def get_config(self):\n\n        config = super().get_config().copy()\n        config.update({\n            'num_classes': self.num_classes,\n            's': self.s,\n            'm': self.m,\n            'input_embedding_dims': self.input_embedding_dims\n        })\n        return config\n\n    \n    def call(self,X):\n\n        #### Normalizing Layers\n        W = tf.nn.l2_normalize(self.W, axis=0)\n        X = tf.nn.l2_normalize(X, axis=1)\n\n        #### Logits Computation\n        logits = X @ W\n        #z = tf.linalg.matmul(X,W) #Logits\n\n        #### Additive Angular Margin \n        #theta = tf.acos(tf.keras.backend.clip(logits, -1.0 + tf.keras.backend.epsilon(), 1.0 - tf.keras.backend.epsilon())) #tf.math.acos(z)\n        #z = self.s*(tf.math.cos(theta+(self.m*y)))  # Final Logits\n\n        return logits  #tf.keras.layers.Softmax(axis=1)(z) # Returning Softmax Activated Result \n\n##### Loss \nclass ArcLoss(tf.keras.losses.Loss):\n\n    def __init__(self,num_classes,s,m):\n\n        #### Defining Essentials\n        super().__init__()\n        self.num_classes = num_classes # Number of Classes in the Outut\n        self.s = s # Geodesic Scaled Distance\n        self.m = m # Additive Angular Margin\n\n    def get_config(self):\n\n        config = super().get_config().copy()\n        config.update({\n            'num_classes': self.num_classes,\n            's': self.s,\n            'm': self.m\n        })\n        return config\n\n    def call(self,y_true,logits):\n        \n        theta = tf.acos(tf.keras.backend.clip(logits, -1.0 + tf.keras.backend.epsilon(), 1.0 - tf.keras.backend.epsilon()))\n        target_logits = tf.cos(theta + self.m)\n        # sin = tf.sqrt(1 - logits**2)\n        # cos_m = tf.cos(logits)\n        # sin_m = tf.sin(logits)\n        # target_logits = logits * cos_m - sin * sin_m\n        #\n        logits = logits * (1 - y_true) + target_logits * y_true\n        # feature re-scale\n        logits *= self.s\n        out = tf.nn.softmax(logits)    \n        \n        return tf.keras.losses.categorical_crossentropy(y_true,out)\n\n        #z = self.s*(tf.math.cos(theta+(self.m*y_true)))\n        #final_logits = tf.keras.layers.Softmax(axis=1)(z) # Softmax Operated Final Logits\n        #return ","metadata":{"execution":{"iopub.status.busy":"2021-07-14T14:33:58.821066Z","iopub.execute_input":"2021-07-14T14:33:58.821480Z","iopub.status.idle":"2021-07-14T14:33:58.837076Z","shell.execute_reply.started":"2021-07-14T14:33:58.821445Z","shell.execute_reply":"2021-07-14T14:33:58.835631Z"},"trusted":true},"execution_count":11,"outputs":[]},{"cell_type":"markdown","source":"# Model Training","metadata":{}},{"cell_type":"code","source":"####### Phase-1 Models\n###### Defining Architecture\n\nwith tpu_strategy.scope():\n\n    ##### SC_Module \n\n    #### Defining Hyperparameters\n    num_layers = 2\n    d_model = 512\n    num_heads = 8\n    dff = 1024\n    max_seq_len = 1280 #X_train.shape[1]\n    pe_input = 320\n    rate = 0.5\n    num_features = 1\n    num_classes = 10\n\n    #### Defining Layers\n    Input_layer = tf.keras.layers.Input(shape=(max_seq_len,num_features))\n    self_conv1 = self_cal_Conv1D(128,15,128)\n    self_conv2 = self_cal_Conv1D(128,20,128) # Newly Added\n    self_conv3 = self_cal_Conv1D(256,15,128)\n    self_conv4 = self_cal_Conv1D(256,20,256) # Newly Added\n    self_conv5 = self_cal_Conv1D(512,15,256)\n    self_conv6 = self_cal_Conv1D(512,20,512) # Newly Added\n    self_conv7 = self_cal_Conv1D(1024,3,512)\n    self_conv8 = self_cal_Conv1D(1024,5,1024) # Newly Added\n    conv_initial = tf.keras.layers.Conv1D(32,15,padding='same',activation='relu')\n    conv_second = tf.keras.layers.Conv1D(64,15,padding='same',activation='relu')\n    conv_third = tf.keras.layers.Conv1D(128,15,padding='same',activation='relu')\n    #lstm1 = tf.keras.layers.Bidirectional(tf.keras.layers.LSTM(128,activation='tanh',return_sequences=True),merge_mode='ave')\n    transform_1 = tf.keras.layers.Conv1D(128,3,padding='same',kernel_initializer='lecun_normal', activation='selu')\n    transform_2 = tf.keras.layers.Conv1D(256,3,padding='same',kernel_initializer='lecun_normal', activation='selu')\n    transform_3 = tf.keras.layers.Conv1D(512,3,padding='same',kernel_initializer='lecun_normal', activation='selu')\n    transform_4 = tf.keras.layers.Conv1D(1024,3,padding='same',kernel_initializer='lecun_normal', activation='selu')\n    transformer = Transformer(num_layers,d_model,num_heads,dff,pe_input,rate)\n    gap_layer = tf.keras.layers.GlobalAveragePooling1D()\n    ArcFace_Layer = ArcFace(10,30.0,0.3,256)\n    ArcFace_Loss = ArcLoss(10,30.0,0.3)\n    #arc_logit_layer = ArcFace(89,30.0,0.3,tf.keras.regularizers.l2(1e-4))\n\n    #### Defining Architecture\n    ### Input Layer\n    Inputs = Input_layer\n    #Input_Labels = tf.keras.layers.Input(shape=(num_classes,))\n\n    ### Initial Convolutional Layers\n    conv_initial = conv_initial(Inputs)\n    #conv_initial = tf.keras.layers.LayerNormalization()(conv_initial)\n    #conv_initial = tf.keras.layers.MaxPool1D(pool_size=2,strides=2)(conv_initial)     \n    #conv_initial = tf.keras.layers.Add()([conv_initial,Inputs])\n    \n    conv_second = conv_second(conv_initial)\n    #conv_second = tf.keras.layers.LayerNormalization()(conv_second)\n    #conv_second = tf.keras.layers.MaxPool1D(pool_size=2,strides=2)(conv_second)\n    #conv_second = tf.keras.layers.Add()([conv_second,conv_initial])\n    #conv_second = tf.keras.layers.concatenate(axis=2)([conv_initial,conv_second])\n    \n    conv_third = conv_third(conv_second)\n    #conv_third = tf.keras.layers.LayerNormalization()(conv_third)\n    #conv_third = tf.keras.layers.MaxPool1D(pool_size=2,strides=2)(conv_third)\n    #mask = tf.keras.layers.MaxPool1D(pool_size=2,strides=2)(Inputs)\n    #conv_third = tf.keras.layers.Add()([conv_third,conv_second])\n    #conv_third = tf.keras.layers.concatenate(axis=2)([conv_initial,conv_second,conv_third])\n    #conv_third = lstm1(conv_second)\n    #conv_third = tf.keras.layers.Attention()([conv_third,conv_third])\n    \n    ### 1st Residual Block\n    transform_1 = transform_1(conv_third)\n    conv1 = self_conv1(conv_third)\n    #conv1 = tf.keras.layers.AlphaDropout(rate=0.2)(conv1)\n    conv2 = self_conv2(conv1)\n    #conv2 = tf.keras.layers.AlphaDropout(rate=0.2)(conv2)\n    conv2 = tf.keras.layers.Add()([conv2,transform_1])\n    #conv2 = tf.keras.layers.LayerNormalization()(conv2)\n    conv2 = tf.keras.layers.MaxPool1D(pool_size=2,strides=2)(conv2)\n    #mask = tf.keras.layers.MaxPool1D(pool_size=2,strides=2)(mask)    \n\n    ### 2nd Residual Block\n    #conv_third = tf.keras.layers.Attention()([conv_third,conv_third])\n    transform_2 = transform_2(conv2)\n    conv3 = self_conv3(conv2)\n    #conv3 = tf.keras.layers.AlphaDropout(rate=0.2)(conv3)\n    conv4 = self_conv4(conv3)\n    #conv4 = tf.keras.layers.AlphaDropout(rate=0.2)(conv4)\n    conv4 = tf.keras.layers.Add()([conv4,transform_2])\n    #conv4 = tf.keras.layers.LayerNormalization()(conv4)\n    conv4 = tf.keras.layers.MaxPool1D(pool_size=2,strides=2)(conv4)\n    #mask = tf.keras.layers.MaxPool1D(pool_size=2,strides=2)(mask)\n\n    ### 3rd Residual Block\n    transform_3 = transform_3(conv4)\n    conv5 = self_conv5(conv4)\n    #conv5 = tf.keras.layers.AlphaDropout(rate=0.2)(conv5)\n    conv6 = self_conv6(conv5)\n    #conv6 = tf.keras.layers.AlphaDropout(rate=0.2)(conv6)\n    conv6 = tf.keras.layers.Add()([conv6,transform_3])\n    #conv6 = tf.keras.layers.LayerNormalization()(conv6)\n    #conv6 = tf.keras.layers.MaxPool1D(pool_size=2,strides=2)(conv6)\n\n    ### 4th Residual Block\n    #transform_4 = transform_4(conv6)\n    #conv7 = self_conv7(conv6)\n    #conv8 = self_conv8(conv7)\n    #conv8 = tf.keras.layers.Add()([conv8,transform_4])\n\n    ### Transformer\n    ## Wide-Head Attention Model\n    #tx_embedding = tf.keras.layers.Lambda(PE_Layer)(Inputs)\n    #tx_embedding = tf.keras.layers.Dropout(rate)(tx_embedding,training=True)\n    #mask_reshaped = tf.keras.layers.Reshape((max_seq_len,))(Inputs)\n    #encoder_op1 = encoder_block1(tx_embedding,mask_reshaped)\n    #encoder_op2 = encoder_block2(encoder_op1,mask_reshaped)\n\n    ## Narrow-Head Attention Model\n    #mask_reshaped = tf.keras.layers.Reshape((160,))(mask)\n    embeddings =  transformer(inp=conv6,enc_padding_mask=None)\n    #embeddings = transformer(inp=conv6,enc_padding_mask=create_padding_mask(mask))\n    #residual_embeddings = tf.keras.layers.Add()([conv6,embeddings])\n\n    ### Output Layers\n    ## Initial Layers\n    gap_op = gap_layer(embeddings)\n    dense1 = tf.keras.layers.Dense(256,activation='relu')(gap_op)\n    dropout1 = tf.keras.layers.Dropout(rate)(dense1)\n    \n    ## ArcFace Output Network\n    dense2 = tf.keras.layers.Dense(256,kernel_initializer='he_normal',\n                kernel_regularizer=tf.keras.regularizers.l2(1e-4))(dropout1)\n    dense3 = ArcFace_Layer(dense2)\n    ##dense2 = tf.keras.layers.BatchNormalization()(dense2)\n    #dense3 = arc_logit_layer(([dense2,Input_Labels]))\n    \n    ## Softmax Output Network\n    #dense2 = tf.keras.layers.Dense(256,activation='relu')(dropout1)\n    ###dropout2 = tf.keras.layers.Dropout(rate)(dense2) # Not to be included\n    #dense3 = tf.keras.layers.Dense(35,activation='softmax')(dense2)\n\n    #### Compiling Architecture            \n    ### ArcFace Model Compilation\n    model = tf.keras.models.Model(inputs=Inputs,outputs=dense3)\n    ### Softmax Model Compilation\n    #model = tf.keras.models.Model(inputs=Inputs,outputs=dense3)\n    \n    #model.load_weights('../input/ecg1d-models/Identification_ECG1D.h5')\n    model = tf.keras.models.Model(inputs=Inputs,outputs=dense3)\n    model.load_weights('./OSV_Train_MITBIH.h5')\n    model.compile(optimizer=tf.keras.optimizers.Adam(lr=1e-4,clipnorm=1.0),loss=ArcFace_Loss,metrics=['accuracy'])\n\nmodel.summary()      \ntf.keras.utils.plot_model(model)\n##### Model Training \n\n#### Model Checkpointing\nfilepath = './OSV_Train_MITBIH.h5'\ncheckpoint = tf.keras.callbacks.ModelCheckpoint(filepath,monitor='val_accuracy',save_best_only=True,mode='max',save_weights_only=True)\n\n#### Model Training\n#model.fit(X_train,y_train_ohot,epochs=250,batch_size=128,\n#          validation_data=(X_dev,y_dev_ohot),validation_batch_size=128,\n#         callbacks=checkpoint)\n\n##### Plotting Metrics  \n#### Accuracy and Loss Plots \n\n### Accuracy\n#plt.plot(history.history['accuracy'])\n#plt.plot(history.history['val_accuracy'])\n#plt.title('Model Accuracy')\n#plt.ylabel('Accuracy')\n#plt.xlabel('Epoch')  \n#plt.legend(['Train', 'Validation'], loc='best')\n#plt.show()\n\n### Loss     \n#plt.plot(history.history['loss'])  \n#plt.plot(history.history['val_loss'])\n#plt.title('Model Loss')  \n#plt.ylabel('Loss')         \n#plt.xlabel('epoch')\n#plt.legend(['Train', 'Validation'], loc='best')   \n#plt.show()","metadata":{"execution":{"iopub.status.busy":"2021-07-14T15:34:06.737349Z","iopub.execute_input":"2021-07-14T15:34:06.737783Z","iopub.status.idle":"2021-07-14T15:34:11.126817Z","shell.execute_reply.started":"2021-07-14T15:34:06.737749Z","shell.execute_reply":"2021-07-14T15:34:11.125758Z"},"trusted":true},"execution_count":20,"outputs":[{"name":"stdout","text":"Model: \"model_5\"\n__________________________________________________________________________________________________\nLayer (type)                    Output Shape         Param #     Connected to                     \n==================================================================================================\ninput_4 (InputLayer)            [(None, 1280, 1)]    0                                            \n__________________________________________________________________________________________________\nconv1d_110 (Conv1D)             (None, 1280, 32)     512         input_4[0][0]                    \n__________________________________________________________________________________________________\nconv1d_111 (Conv1D)             (None, 1280, 64)     30784       conv1d_110[0][0]                 \n__________________________________________________________________________________________________\nconv1d_112 (Conv1D)             (None, 1280, 128)    123008      conv1d_111[0][0]                 \n__________________________________________________________________________________________________\nself_cal__conv1d_16 (self_cal_C (None, 1280, 128)    266560      conv1d_112[0][0]                 \n__________________________________________________________________________________________________\nself_cal__conv1d_17 (self_cal_C (None, 1280, 128)    348480      self_cal__conv1d_16[0][0]        \n__________________________________________________________________________________________________\nconv1d_113 (Conv1D)             (None, 1280, 128)    49280       conv1d_112[0][0]                 \n__________________________________________________________________________________________________\nadd_6 (Add)                     (None, 1280, 128)    0           self_cal__conv1d_17[0][0]        \n                                                                 conv1d_113[0][0]                 \n__________________________________________________________________________________________________\nmax_pooling1d_4 (MaxPooling1D)  (None, 640, 128)     0           add_6[0][0]                      \n__________________________________________________________________________________________________\nself_cal__conv1d_18 (self_cal_C (None, 640, 256)     389568      max_pooling1d_4[0][0]            \n__________________________________________________________________________________________________\nself_cal__conv1d_19 (self_cal_C (None, 640, 256)     1393280     self_cal__conv1d_18[0][0]        \n__________________________________________________________________________________________________\nconv1d_114 (Conv1D)             (None, 640, 256)     98560       max_pooling1d_4[0][0]            \n__________________________________________________________________________________________________\nadd_7 (Add)                     (None, 640, 256)     0           self_cal__conv1d_19[0][0]        \n                                                                 conv1d_114[0][0]                 \n__________________________________________________________________________________________________\nmax_pooling1d_5 (MaxPooling1D)  (None, 320, 256)     0           add_7[0][0]                      \n__________________________________________________________________________________________________\nself_cal__conv1d_20 (self_cal_C (None, 320, 512)     1557376     max_pooling1d_5[0][0]            \n__________________________________________________________________________________________________\nself_cal__conv1d_21 (self_cal_C (None, 320, 512)     5571840     self_cal__conv1d_20[0][0]        \n__________________________________________________________________________________________________\nconv1d_115 (Conv1D)             (None, 320, 512)     393728      max_pooling1d_5[0][0]            \n__________________________________________________________________________________________________\nadd_8 (Add)                     (None, 320, 512)     0           self_cal__conv1d_21[0][0]        \n                                                                 conv1d_115[0][0]                 \n__________________________________________________________________________________________________\ntransformer_2 (Transformer)     (None, 320, 512)     4205568     add_8[0][0]                      \n__________________________________________________________________________________________________\nglobal_average_pooling1d_2 (Glo (None, 512)          0           transformer_2[0][0]              \n__________________________________________________________________________________________________\ndense_40 (Dense)                (None, 256)          131328      global_average_pooling1d_2[0][0] \n__________________________________________________________________________________________________\ndropout_17 (Dropout)            (None, 256)          0           dense_40[0][0]                   \n__________________________________________________________________________________________________\ndense_41 (Dense)                (None, 256)          65792       dropout_17[0][0]                 \n__________________________________________________________________________________________________\narc_face_2 (ArcFace)            (None, 10)           2560        dense_41[0][0]                   \n==================================================================================================\nTotal params: 14,628,224\nTrainable params: 14,628,224\nNon-trainable params: 0\n__________________________________________________________________________________________________\n","output_type":"stream"}]},{"cell_type":"code","source":"####### Phase-2 Model \n\n###### With Dense\nwith tpu_strategy.scope():\n\n    ##### SC-Net based Model \n    SC_model = tf.keras.models.Model(inputs=model.input,outputs=model.layers[-7].output) # Taking output of SC-Net from Conv6 (-7 for with Dense and -5 for without )\n    SC_model.compile(tf.keras.optimizers.Adam(lr=1e-4),loss='categorical_crossentropy',metrics=['accuracy'])\n    SC_model.trainable = False # Freezing the Trainable Model\n    \nwith tpu_strategy.scope():\n    \n    #### Defining Hyperparameters\n    num_layers = 2\n    d_model = 512\n    num_heads = 8\n    dff = 1024\n    max_seq_len = 1280 #X_train.shape[1]\n    pe_input = max_seq_len\n    rate = 0.5\n    num_features = 1\n    num_classes = 47\n    \n    ##### SC-Net+Transformer Model\n    y_in = tf.keras.layers.Input((47,))\n    Input_Layer = tf.keras.layers.Input((1280,1))\n    op_1 = SC_model([Input_Layer,y_in])\n\n    #### Narrow-Head Attention Transformer Model\n    #mask_reshaped = tf.keras.layers.Reshape((max_seq_len,))(Input_Layer)\n    embeddings = transformer(inp=op_1,enc_padding_mask=None)\n    #residual_embeddings = tf.keras.layers.Add()([conv6,embeddings])\n    \n    #### Output Network\n    ## Initial Layers\n    gap_op = gap_layer(embeddings)\n    dense1 = tf.keras.layers.Dense(256,activation='relu')(gap_op)\n    dropout1 = tf.keras.layers.Dropout(rate)(dense1)\n    \n    ### ArcFace Output Network\n    dense2 = tf.keras.layers.Dense(256,kernel_initializer='he_normal',\n                kernel_regularizer=tf.keras.regularizers.l2(1e-4))(dropout1)\n    ##dense2 = tf.keras.layers.BatchNormalization()(dense2)\n    dense3 = arc_logit_layer(([dense2,y_in]))\n\n    #### Compiling Architecture            \n    ### ArcFace Model Compilation\n    model_transformer = tf.keras.models.Model(inputs=[Input_Layer,y_in],outputs=dense3)\n    ### Softmax Model Compilation\n    #model = tf.keras.models.Model(inputs=Inputs,outputs=dense3)\n    model_transformer.load_weights('./Transfomer_with_Dense_TPTP_MITBIH.h5')\n    model_transformer.compile(tf.keras.optimizers.Adam(lr=1e-4,clipnorm=1.0),loss='categorical_crossentropy',metrics=['accuracy'])\n\nmodel_transformer.summary()      \ntf.keras.utils.plot_model(model_transformer)\n##### Model Training \n\n#### Model Checkpointing\nfilepath = './Transfomer_with_Dense_TPTP_MITBIH.h5'\ncheckpoint = tf.keras.callbacks.ModelCheckpoint(filepath,monitor='val_accuracy',save_best_only=True,mode='max',save_weights_only=True)\n\n#### Model Training\n#### Model Training\n### ArcFace Training\n#history = model_transformer.fit((X_train,y_train_ohot),y_train_ohot,epochs=250,batch_size=128,\n#                validation_data=((X_dev,y_dev_ohot),y_dev_ohot),validation_batch_size=128,\n#               callbacks=checkpoint)\n\n### Softmax Training \n#history = model.fit(X_train,y_train_ohot,epochs=250,batch_size=128,\n#                validation_data=(X_dev,y_dev_ohot),validation_batch_size=128,\n#                callbacks=checkpoint)\n\n##### Plotting Metrics  \n#### Accuracy and Loss Plots \n\n### Accuracy\n#plt.plot(history.history['accuracy'])\n#plt.plot(history.history['val_accuracy'])\n#plt.title('Model Accuracy')\n#plt.ylabel('Accuracy')  \n#plt.xlabel('Epoch')  \n#plt.legend(['Train', 'Validation'], loc='best')\n#plt.show()\n\n### Loss     \n#plt.plot(history.history['loss'])  \n#plt.plot(history.history['val_loss'])\n#plt.title('Model Loss')  \n#plt.ylabel('Loss')         \n#plt.xlabel('epoch')\n#plt.legend(['Train', 'Validation'], loc='best')   \n#plt.show()","metadata":{"execution":{"iopub.status.busy":"2021-05-29T16:37:37.224145Z","iopub.execute_input":"2021-05-29T16:37:37.224536Z","iopub.status.idle":"2021-05-29T16:37:39.718136Z","shell.execute_reply.started":"2021-05-29T16:37:37.224503Z","shell.execute_reply":"2021-05-29T16:37:39.716631Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"##### Plotting Metrics  \n#### Accuracy and Loss Plots \n\n### Accuracy\nplt.plot(history.history['accuracy'])\nplt.plot(history.history['val_accuracy'])\nplt.title('Model Accuracy')\nplt.ylabel('Accuracy')  \nplt.xlabel('Epoch')  \nplt.legend(['Train', 'Validation'], loc='best')\nplt.show()\n\n### Loss     \nplt.plot(history.history['loss'])  \nplt.plot(history.history['val_loss'])\nplt.title('Model Loss')  \nplt.ylabel('Loss')         \nplt.xlabel('epoch')\nplt.legend(['Train', 'Validation'], loc='best')   \nplt.show()","metadata":{"execution":{"iopub.status.busy":"2021-06-08T08:09:43.298613Z","iopub.execute_input":"2021-06-08T08:09:43.298942Z","iopub.status.idle":"2021-06-08T08:09:43.747327Z","shell.execute_reply.started":"2021-06-08T08:09:43.298907Z","shell.execute_reply":"2021-06-08T08:09:43.746221Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"##### Histogram Plot                             \nweights_init = np.array(model.get_weights())     \nweights_init.flatten()\n\nweights_final = []       \n\nfor i in range(101):\n    for item in weights_init[i].flatten():\n        weights_final.append(item)\n    \n#weights_before_train = np.array(weights_final)\n#print(weights_before_train.shape)   \n    \nweights_after_train = np.array(weights_final)\nprint(weights_after_train.shape)","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"weight_main = np.absolute(weights_after_train) #-weights_before_train)\nprint(weight_main.shape)\nfor item in [10]:\n    plt.hist(weight_main,bins=int(item))\n    item_path = 'hist_plot_'+str(item)+'.png'\n    plt.savefig(item_path)\n    plt.show()","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Model Testing","metadata":{}},{"cell_type":"markdown","source":"## KNN Testing based on ArcFace Loss","metadata":{}},{"cell_type":"code","source":"###### Testing Model - ArcFace Style\nwith tpu_strategy.scope():     \n\n    def normalisation_layer(x):   \n        return(tf.math.l2_normalize(x, axis=1, epsilon=1e-12))\n\n    #X_dev_flipped = tf.image.flip_up_down(X_dev)  \n    #x_train_flipped = tf.image.flip_up_down(X_train_final)\n\n    predictive_model = tf.keras.models.Model(inputs=model.input,outputs=model.layers[-3].output)\n    predictive_model.compile(tf.keras.optimizers.Adam(lr=1e-4),loss='categorical_crossentropy',metrics=['accuracy'])\n\nwith tpu_strategy.scope():\n    #y_in = tf.keras.layers.Input((89,))\n\n    Input_Layer = tf.keras.layers.Input((1280,1))\n    op_1 = predictive_model(Input_Layer)\n\n    ##Input_Layer_Flipped = tf.keras.layers.Input((224,224,3))\n    ##op_2 = predictive_model([Input_Layer_Flipped,y_in]) \n    ##final_op = tf.keras.layers.Concatenate(axis=1)(op_1)\n\n    final_norm_op = tf.keras.layers.Lambda(normalisation_layer)(op_1)\n\n    testing_model = tf.keras.models.Model(inputs=Input_Layer,outputs=final_norm_op)\n    testing_model.compile(tf.keras.optimizers.Adam(lr=1e-4),loss='categorical_crossentropy',metrics=['accuracy'])\n\n##### Nearest Neighbor Classification\nfrom sklearn.neighbors import KNeighborsClassifier\nTest_Embeddings = testing_model.predict(X_dev)\nTrain_Embeddings = testing_model.predict(X_train)\n\ncol_mean = np.nanmean(Test_Embeddings, axis=0)\ninds = np.where(np.isnan(Test_Embeddings))\n#print(inds)\nTest_Embeddings[inds] = np.take(col_mean, inds[1])\n\ncol_mean = np.nanmean(Train_Embeddings, axis=0)\ninds = np.where(np.isnan(Train_Embeddings))\n#print(inds)\nTrain_Embeddings[inds] = np.take(col_mean, inds[1])\n\n#Test_Embeddings = np.nan_to_num(Test_Embeddings)\n\n##### Refining Test Embeddings\n#for i in range(Train_Embeddings.shape[0]):\n#    for j in range(Train_Embeddings.shape[1]):\n#        if(math.isnan(Train_Embeddings[i,j])):\n#            Train_Embeddings[i,j] == 0\n#        if(Train_Embeddings[i,j]>1e4):\n#            Train_Embeddings[i,j] == 1e4\n\n##### Refining Train Embeddings    \n#for i in range(Test_Embeddings.shape[0]):\n#    for j in range(Test_Embeddings.shape[1]):\n#        if(math.isnan(Test_Embeddings[i,j])):\n#            Test_Embeddings[i,j] == 0\n#        if(Test_Embeddings[i,j]>1e4 or math.isinf(Test_Embeddings[i,j])):\n#            Test_Embeddings[i,j] == 1e4\n\n#del(X_train_final,X_dev,X_dev_flipped,x_train_flipped)\n#gc.collect()\n\nTest_Accuracy_With_Train = []\nTest_Accuracy_With_Test = []\n                                                                     \nfor k in range(1,11):\n    knn = KNeighborsClassifier(n_neighbors=k,metric='euclidean')\n    knn.fit(Train_Embeddings,y_train)\n    Test_Accuracy_With_Train.append(knn.score(Test_Embeddings,y_dev))\n    knn.fit(Test_Embeddings,y_dev)\n    Test_Accuracy_With_Test.append(knn.score(Test_Embeddings,y_dev))\n\nprint('--------------------------------')\nprint(np.max(Test_Accuracy_With_Train))\nprint(np.max(Test_Accuracy_With_Test))\nprint('--------------------------------')\nprint(np.mean(Test_Accuracy_With_Train))\nprint(np.mean(Test_Accuracy_With_Test))\nprint('--------------------------------')\nprint((Test_Accuracy_With_Train)[0])\nprint((Test_Accuracy_With_Test)[0])\nprint('--------------------------------')\n\nplt.plot(np.arange(1,11),np.array(Test_Accuracy_With_Train),label='Test_Accuracy_With_Train')\nplt.plot(np.arange(1,11),np.array(Test_Accuracy_With_Test),label='Test_Accuracy_With_Test')\nplt.title('Testing Accuracy vs Number of Neighbors')\nplt.xlabel('Number of Neighbors')\nplt.ylabel('Test Accuracy')\nplt.legend()       \nplt.show()  \n\nnp.savez_compressed('TesEmb_ECG1D_OSV_MITBIH.npz',Test_Embeddings)\nnp.savez_compressed('TrainEmb_ECG1D_OSV_MITBIH.npz',Train_Embeddings)","metadata":{"execution":{"iopub.status.busy":"2021-07-14T15:38:00.926344Z","iopub.execute_input":"2021-07-14T15:38:00.926765Z","iopub.status.idle":"2021-07-14T15:38:28.868700Z","shell.execute_reply.started":"2021-07-14T15:38:00.926727Z","shell.execute_reply":"2021-07-14T15:38:28.867465Z"},"trusted":true},"execution_count":23,"outputs":[{"name":"stdout","text":"--------------------------------\n0.9707724425887265\n1.0\n--------------------------------\n0.9631871955462771\n0.9736951983298539\n--------------------------------\n0.9707724425887265\n1.0\n--------------------------------\n","output_type":"stream"},{"output_type":"display_data","data":{"text/plain":"<Figure size 432x288 with 1 Axes>","image/png":"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XxEWFsZ1113HmDFj8vpUq1WrFklJSYwbN47ExEQeeOABNmzYwMaNG2nUqBGPPfYYI0eO5NChQwA8//zzeQlswoQJvP3224SFhTFkyBCuu+46LrzwQpYsWQLAunXruPjii/OmfSUkJBAfH8/69etp0aIF27ZtY8SIESxYsIBzzz2XBQsW8PDDD7N582bOPvtslixZwn333ceRI0eYP38+d93lnKpWrlxJv379+P3337ntttuK9Uv/qquuIiYmhp9//pnevXtzySWXMHbsWNLS0qhUqRJTpkyhVatWJCYmMnHiRD777DMeeOABfv/9dzZu3FiifRYkaAlCRKbilARqichWnCuTIgFUdTLOGLJDccaEPYwzaDiquk9EHgIWuZsar6qFNXaXjtNuhB8mOw3Wo2YEfXfGeEVVGTNmDNOnTychIYFp06Zxzz338Nprr/H444+zadMmoqOj2b9/P9WqVWP06NEBlTqmTZvGrFmzWL16NZMmTeKyyy4jIyODiy++mGnTptGtWzdSUlKoVKkSL730Eps3b2bp0qVERESwb1/RX/GVK1cyf/58KlWqxOHDh5k1axYxMTGsW7eOSy+9lKSkJL788kumT5/Ojz/+SOXKldm3bx81atSgatWqLF26lE6dOjFlyhSuvvrqAvfTu3dvFixYQHZ2Ni1btqRHjx7MnDmTs88+m19++YVu3bqxc+dOAKKiohg/fjxJSUk8//zzgFMaWL16NXPmzCE1NZVWrVpx4403FusGta1bt7JgwQLCw8NJSUlh3rx5RERE8M0333D33Xfzv//975jnHO8+/QlaglDVS4tYrsDNBSx7DWeA9LITXQX6/BNm3gUbv4Nmfct09+bEUNxf+sGQnp7O8uXLGThwIADZ2dnUrVsXgA4dOnD55Zdz7rnnHlUXX5TcX/2NGjWifv36XHPNNezbt49t27ZRt25dunXrBkB8fDwA33zzDaNHj86rPqlRo0aR+xg2bBiVKlUCnLvTb7nlFpYuXUp4eDhr167N2+7VV19N5cqVj9rutddey5QpU3jqqaeYNm0aP/30U4H76dWrV16C6NmzJ927d2f8+PH8/PPPnHLKKcTExBQZ61lnnUV0dDTR0dHUrl2bXbt20aBBgyKfl+vCCy8kPDwcgAMHDjBq1CjWrVuHiJCZmRmUffpTrhupS13XayC+Pnz7ENhIe6aC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\n"},"metadata":{"needs_background":"light"}}]},{"cell_type":"code","source":"###### Testing Model - Softmax Style Model\n\nwith tpu_strategy.scope():\n\n    def normalisation_layer(x):\n        return(tf.math.l2_normalize(x, axis=1, epsilon=1e-12))\n\n    #X_dev_flipped = tf.image.flip_up_down(X_dev)\n    #x_train_flipped = tf.image.flip_up_down(X_train_final)\n\n    predictive_model = tf.keras.models.Model(inputs=model.input,outputs=model.layers[-2].output)\n    predictive_model.compile(tf.keras.optimizers.Adam(lr=1e-4),loss='categorical_crossentropy',metrics=['accuracy'])\n\n    #y_in = tf.keras.layers.Input((24,))\n\n    Input_Layer = tf.keras.layers.Input((1280,1))\n    op_1 = predictive_model(Input_Layer)\n      \n    ##Input_Layer_Flipped = tf.keras.layers.Input((224,224,3))\n    ##op_2 = predictive_model([Input_Layer_Flipped,y_in]) \n    ##final_op = tf.keras.layers.Concatenate(axis=1)(op_1)\n\n    final_norm_op = tf.keras.layers.Lambda(normalisation_layer)(op_1)\n\n    testing_model = tf.keras.models.Model(inputs=Input_Layer,outputs=op_1)\n    testing_model.compile(tf.keras.optimizers.Adam(lr=1e-4),loss='categorical_crossentropy',metrics=['accuracy'])\n\n##### Nearest Neighbor Classification\nfrom sklearn.neighbors import KNeighborsClassifier\nTest_Embeddings = testing_model.predict((X_dev,y_dev_ohot))\nTrain_Embeddings = testing_model.predict((X_train,y_train_ohot))\n\nTest_Accuracy_With_Train = []\nTest_Accuracy_With_Test = []\n                                                                     \nfor k in range(1,26):\n    knn = KNeighborsClassifier(n_neighbors=k,metric='euclidean')\n    knn.fit(Train_Embeddings,y_train)\n    Test_Accuracy_With_Train.append(knn.score(Test_Embeddings,y_dev))\n    knn.fit(Test_Embeddings,y_dev)\n    Test_Accuracy_With_Test.append(knn.score(Test_Embeddings,y_dev))\n\nprint(np.max(Test_Accuracy_With_Train))\nprint(np.max(Test_Accuracy_With_Test))\nprint(np.mean(Test_Accuracy_With_Train))\nprint(np.mean(Test_Accuracy_With_Test))\n\nplt.plot(np.arange(1,26),np.array(Test_Accuracy_With_Train),label='Test_Accuracy_With_Train')\nplt.plot(np.arange(1,26),np.array(Test_Accuracy_With_Test),label='Test_Accuracy_With_Test')\nplt.title('Testing Accuracy vs Number of Neighbors')\nplt.xlabel('Number of Neighbors')\nplt.ylabel('Test Accuracy')\nplt.legend()       \nplt.show()  ","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## t-SNE Plots","metadata":{}},{"cell_type":"code","source":"####### t-SNE Plot Generation\n###### Model Creation\n#with tpu_strategy.scope():          \n#    tsne_model = tf.keras.models.Model(inputs=model.input,outputs=model.layers[-4].output)\n#    tsne_model.compile(tf.keras.optimizers.Adam(lr=1e-4),loss='categorical_crossentropy',metrics=['accuracy'])\n#tsne_model.summary()\n\n###### Model Predicted\n#embeddings_final = tsne_model.predict((X_dev,y_exp))\n\n###### t-SNE plot plotting\n##### Reduction to Lower Dimensions\ntsne_X_dev = TSNE(n_components=2,perplexity=30,learning_rate=10,n_iter=2000,n_iter_without_progress=50).fit_transform(Test_Embeddings)\n\n##### Plotting\nj = 0 # Index for rotating legend\nplt.rcParams[\"figure.figsize\"] = [18,14]\nmStyles = [\".\",\",\",\"o\",\"v\",\"^\",\"<\",\">\",\"1\",\"2\",\"3\"]\nfor idx,color_index,marker_type in zip(list(np.arange(10)),sns.color_palette('muted',10),mStyles):\n    plt.scatter(tsne_X_dev[y_dev == idx, 0], tsne_X_dev[y_dev == idx, 1],marker=marker_type)\nplt.legend([str(j) for j in range(47)],loc='best')\nplt.savefig('tsne_plot_5000_iters.png')\nplt.savefig('tsne_plot_5000_iters.pdf')\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2021-07-14T15:39:36.294872Z","iopub.execute_input":"2021-07-14T15:39:36.295286Z","iopub.status.idle":"2021-07-14T15:39:50.392113Z","shell.execute_reply.started":"2021-07-14T15:39:36.295248Z","shell.execute_reply":"2021-07-14T15:39:50.390942Z"},"trusted":true},"execution_count":24,"outputs":[{"output_type":"display_data","data":{"text/plain":"<Figure size 1296x1008 with 1 Axes>","image/png":"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n0e9HgMLRERERBSZeB7W5VkFRsdG6k2PICJKUfV1h9Hd3o/6t5ow987xMVnzn//5n/HUU0+hp6cnJusxsEBERESU7pJ9LGOsRlsO5nhMIqJB4OhyYt/WFkAE9n3YjOrrx0adtfCnP/0JZWVlmDFjBjZt2hSTfTKwQERERJTuHjmRXD0OWJZARGRIfd1hiD4RACD6xJhkLWzZsgVvvPEG3nrrLfT396O7uxtf//rX8b//+78Rr8nmjUREREQ0uFYUBv7viRGJ3hERUdKRshV83oHAgs8rYt+HzXB0OaNa98knn8Tx48fR1NSEV155BVdddVVUQQWAGQtEREREpEevb4FeU8Vwyi9iVaahtR8tsSrBICKKA3m2giRWWQuxxsACERERUSYI1dgwkqkLWuUVrl71codIyzGMNmUMN0CRzH0niCjjHf6k3Z+tIPF5RRzefTpmgYV58+Zh3rx5Ua/DwAIRERFRJlALEMRijONgSKa9EBENkntXXpHoLRjGHgtEREREmcroGEc17ItARETnMLBAREREROFjGQEREZ3DwAIRERERDQ5lT4RQjxMRUUpgjwUiIiIiii2tQEEkvRLC6QMRziQK6XoiIooaAwtEREREFFuxbLYYTh8I6X31pk+oTasgIqKoMLBARERElKmMjnFMBK1MBSP0MheeGMEpE0SU8caOHYv8/HyYzWZYLBbU19dHtR4DC0RERESZKpoDdryDEtE0h3zkhHbWAptOEhEBAN577z2UlJTEZC0GFoiIiIgofPHulzDYknlvREQAejvOYNu61Ti0cwe+/asXEr2dAAwsEBEREdHgMNIvIZoSiGiE08uBiGgQSQGFPZveBUQfvB5P1GsKgoCamhoIgoBvf/vbuP/++6Naj4EFIiIiIkoeRg/yydAHgogojuIRUJB88MEHGDFiBNra2nDNNddgwoQJuPLKKyNej4EFIiIiIoreYGYacLIDEWWAVx59GF2nWgFRjPnaI0aMAACUlZXhlltuwY4dO6IKLJhitTEiIiIiymCDFVQwmqmgdR0zHYgoRdz546dx6TVfhsVmg9kSu5wAh8OBnp4e/683bNiASy65JKo1mbFARERERImnNcUh4JowMhWkhovKTApX78B7yZsyPjHC+LpERIPEXlSMqxcvw2W33omt61bjs00bIfqiL4lobW3FLbfcAgDweDz42te+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ivDVr34V//u//4uvf/3rEa/JwAIREaWccePGYdGiRYanPQDBAQMtykCCnHxqBEdOEqW5cCZAhJMxEEqiezUQUVLpdRzA3n0PAwD27nsYU6f+Hnn2C6Nac+PGjbjgggv8f39auHAhPvzwQwYWiIgoszQ0NPhHTvb396OhoSHkAV8vYKD3PmrjJ+UTKThykiiNyAMEekEFrcO/LS9xpQaJfG8iigunsxUffXQjTKYcFBdfhp6evfjooxtx+WWbkJU1LOJ1R48ejW3btuHs2bPIycnBu+++i+rq6qj2ysACERGlFGkspNlsRmFhIV577TV4vV7VA340GQZ64yebmpo4cpIoncQqS0BZqhBO1kOs31uvNEJ6jqMoiZJaVtYwTBj/OIYOnQubrQQu12m0t78fVVABAGbNmoXbbrsN06dPh8ViwbRp03D//fdHtaYgimJUC8RSdXW1WF9fn+htEBFRkjt16hReeukldHd3o6CgAN/4xjdw4sSJgCDCp59+io0bNwYEBtxuN2prawOCAXrBB7X36enpwYsvvoi7774blZWVCfoGiAbHziMd2NbYjtmVQzFjjHpz1JShdcjXOlzrHszDCERE2vtAa19GP0e4pRwMMBANin379mHixImJ3oYhansVBGGnKIpB6Q3MWCAiopQjTXmQeixkZWUFZRe43W58/etfx/r169HU1IT8/HwsXrwYJpPJXzqhlpXgdrvR19eHyZMno7S0FNdddx3++Mc/+ns59PYO/EWdIycp3e080oG7frsNLo8PNosJf7hvdmoHF1Lt4OzqDQxKSId/rWCB8nH55w0V3GAJBRFFiYEFIiJKSfIpDwUFBViyZAleeumlgDKF0tJS1NTUYO3atejv70ddXV1QbwTl6+644w689NJL+Nvf/oby8nKcODHwl/O+vj4AxptAEqW6bY3tcHl88ImA2+PDtsb21A4spLpwD/+DWYZBRBnPlOgNEBERRUJ5wJeyGAAETIqw2+0AAKvViqamJthsNixZssRfDqF83dixY7FkyRLYbDY0NTUhKysLM2fOxPDhwwGcbwJZXMwDFqW32ZVDYbOYYBYAq8WE2ZVDE72lwaU16SHcCRCxnBgRyorCgf9FElR4YkR89kREGYEZC0RElJLUpjzIsxgkUgBi6NChePXVV1XHUypfJy+1WLhwIXspUEaaMaYYf7hvdvr0WAhXrEonQq0TaQ8GPZFkKjC7gYiiwIwFIiJKWQ0NDf6eB729vTh58mRQmcKRI0cwc+ZM5OfnAwAOHToUtI5aeYMy2CB/r23btmH79u3+921oaIj1RyNKCjPGFOOB+VWZF1TIVFK2AxFRmJixQERESU9tckNlZaVq40X51Ad5c8aSkhJYLBZs27YNs2bNCpgMoZb9IA82KNc5fvw4AGDPnj04depUQM8GIqKw2PKMZwvEI7tBiZkLRBQBjpskIqKk1t3djVWrVqkGEJxOZ9A4SGWZw6lTp/Dcc8+hr68PBQUFuPXWW9HR0eEfKWmUfPSk3W6HIAjo7e3VfF8ioogkU9NFjqEkirlkGTe5atUq/OY3v4EoiviHf/gH/PM//3PQNeGMm2QpBBERJTVpcoPUTFHefFGrYaNcVlYWnE4nACAnJwerV6/Gm2++ie7ubtX3U5ZXSGUO8ve69dZbsXDhQt33JSKKyCMngBVdgf+LRCyaRrp6WRpBlIb27NmD3/zmN9ixYwd2796NP/3pTzh48GBUa7IUgoiIkp68meLNN9+MEydOICcnB3l5eejv7wcQ2LAROF8+UVBQgGuvvRZ//vOf0dra6h9FqVa2IC95kGdHSGUOas0hle9LRJRwepkG4ZZTuHrPv4YZDEQJ1eJ0ozzLGvU6+/btw6xZs5CbmwsAmDt3Ll599VU8/PDDEa/JwAIREaUE6QDf19cXcPg/efIkBEGAxXL+P2nKAEFzczMEQYAoiroZBlJ2xEsvvYSmpqagIISyyaOy4SMR0aCLNKMhEslSokGUgfY7+lFTvx9PXTQKiyqGRLXWJZdcgh/84Adob29HTk4O3nrrLVRXB1U3hIWlEERElBKkQ/3w4cMDSiOys7OxbNkytLe3+0sYTCYT5s2b578mKysLN954IwD1KQ9aJQ/KIITU5LG4uDjg10RERESxdrTPiS0dPfigowd37j6EXJMJXxoafaPoiRMn4nvf+x5qampw3XXXYerUqTCbzVGtyYwFIiJKCcrJDfLSiKysLH+GgjQ5wu124/rrr8ebb76Jm2++GcXFxapTHoyWPBARJYzW5IhY9FEgoqS1puUMftbU6v95TlEeSmyxOcIvXrwYixcvBgA88sgjGDlyZFTrMbBAREQpSX74l0oYXnzxRZw+fRoAMHz4cLz99tsABsonKisrAwIT4ZQ8xIra2Mxwp1MQUQaKZV+DcMZbElFCLSofgsuL8iACqN13FHt6+3DK5UapLfo+C21tbSgrK8PRo0fx6quvYtu2bVGtx8ACERGlJOXhv7S0FLfccgtefPFF5Obm4uTJk8jLy8PUqVMxfPjwoNcrG0KqlTzEkjJL4sSJE/D5fKisrITJZGKQgYgGh1aQIpnGXBIRAGB0ThZG52QBAF6+dBxq6vfjvTM9uL08uh4LwMCEq/b2dlitVvzyl7+M+mYKAwtERBQX8b47r3b4l7IY5syZgw0bNuD666/HpEmT/D0UlO8/mCUPysaQAGCz2fDqq68GlWIQEQ06ecBBK8jA0guihBlvz8b22ZNiMhUCADZv3hyTdSQMLBARUcxt3boVGzduhNVqRWlpKVpaWvx35+N5cJayGKQJEevXr8eOHTs0swP0Sh7UAiMAogqWyLMkbrrpJrz33nuqpRhERAnFkZJESSlWQYV4YGCBiIhiqru7Gxs3boTZbIbb7caxY8cAAPfcc0/UB+dQh32r1Yri4mKMGTMGM2fOxL59+3SzA7RKHrSaO4qiCJvNptrw0SgpO6KoqEizFIOIiIgolTCwQEREMSVP+e/u7gYA3HTTTbjggguiWlftsO9yuSAIQlAAoLa2FgsWLMDEiRMjyg5Qli1IrwEQ8NgVV1wBk2lgcrPRDAZ5lkRnZycATp8gIiKi1GZK9AaIiCj9SCn/klhMV5AO+zabDU1NTbDZbFi6dGnQY/PmzfMf9vv7+/3vL+1Hyg5oaGhAb+9ADbHUg0HrM0ivkT9WU1ODTZs24dlnn8Xzzz+PZ599Fm+++aY/mKJFypIoLi6O2/QJIiIiSl6iKCZ6CyGFu0dmLBARUVxId+EvvfTSmB2ctSY5SI/V1NRg/fr12LJlC8rLy9Hc3AxBEGCxWODxePz70ip1UJY1qDV3lH5tt9t1R1YaEY/pE0RERJS8srOz0d7ejqFDhyZtxqIoimhvb0d2drbh1zCwQEREcSHdjZ86dSqKi4tjtm64h/377rsPpaWl6Ojo8GcHaJU6NDY2BvRwOHnyZFBGgTzLoLi4mH0SiIiIyLCRI0fi+PHjOHXqVKK3ois7OxsjR440fD0DC0REFBfxuhuvVj5g5LCv3I8y+yErK0s1i6G2tjYgC0G5zmCOrCQiIqLUZrVao+47lYzYY4GIiFKKvEeB1mNGD/vy69R6OCxZsgSNjY26vRjYJ4GIiIgyHTMWiIgo7Rg97CuvM5rFIO/FUFxcjOLiYlitA7OljU6HICIiIkoXDCwQEVHaMVKG0dDQgKqqKsyfP9+fiTB16lTVLAa9Bo1GG0ESERERpSsGFoiIKOPoBQNCZTEoGzQaCT4QERERpTP2WCAiooyj1U+hoKBAtYdDqJ4NUvABAKdDEBERUcZhYIGIiDJSOMEAIz0bOB2CiIiIMhUDC0RElLGMBgPUshiUpODDyZMndadIEBEREaUb9lggIqKMFctRkcXFxZgxYwZWrVqFzZs3s5EjERERZQxmLBARUcbSykRoaGiIKOtAr3cDERERUbpixgIREWU0aexkXl4eent78emnn2Ljxo0Rj48MNUWCiIiIKN0wsEBERClNGRg4ePAgpk6daui1WmMnL7vsMjQ0NKCpqQl5eXm44oorsGnTJsyaNQvDhg1Da2srtm/fjhtvvFF1XTZyJCIiokzCwAIREaUEtQBCZWWlamCgsrISjY2NqKqqwsGDB1FRUYHm5mb/z1LgQSpdeOmll9DU1ISCggLccccdeOmll2A2mwEALpcL7733Hnw+H3bt2oXs7Gz09/cDAKqrqzF8+PCgvcaydwMRERFRshNEUUz0Hvyqq6vF+vr6RG+DiIiSTHd3N1atWhUUQKitrYXT6cRLL72E7u5uFBQU4Bvf+AaysrKwatUqWCwWOJ1O/zpZWVnweDyora0NKGtobGzEiy++iLvvvhuVlZU4deoUnn/+eTgcDtjtdtx77704c+YMXnnlFYiiCEEQcMcdd2D8+PGJ+DqIiIiIEkIQhJ2iKFYrH2fzRiIiSnp6TRGlngYA/D0NpOuzsrIAnC9JyMrKwt13343GxsaA9ZWlC6Wlpbj22msBANdeey1KS0sxfvx4XH311QCAq6++mkEFIiIionMYWCAiopSgFkCQqPU0kF8vycnJwerVq/Hmm2+iu7sbwECJhc1mw9y5c2Gz2fwTIPLz8wP+CQAmkyngn5FOjyAiIiJKJ+yxQEREKUOrKaJWTwPpussvvxxbtmxBa2srCgoKsHjxYhQUFAQ1b9y+fbu/R4PamsOHD8eYMWMwfPhwzcaPRqdHEBEREaUL9lggIqKU0dHRgYaGBkydOhXFxcWGr6+srMTOnTvxySef+PsoSE6dOhXUo8HoiMhoXktERESUathjgYiIUl5xcTHmz59vKKggv37MmDGYNm0agOBsB70Si1CieS0RERFRumBggYiIUprRPgdSacPJkyexbds29Pb2ore3F9u3b8ehQ4cABAcdjJBe09/fj4aGBrS2tvr3xJ4LRERElAnYY4GIiJJOQ0MDqqqqkJeXh97eXhw8eBBTp04Nui6cPgfFxcWYMWMGfvGLX8Dn82HDhg0AAJ/PB7PZjNmzZwf1aDDCYrFAEASsX78ebrfb/7g02pI9F4iIiCjdsccCERElle7ubqxatSooWFBbW6t6QNfqc6AVnDh16hSef/55OBwOAEBeXh7uueeeqMoY5HsQBAGiKLLnAhEREaUd9lggIqKUUFBQgCVLlsBms6GpqQk2mw1LlizRvOuv1udAymR49tln8fzzz+PZZ5/1j5gsLS0NyH64/vrrceLEiaj2LN/DpEmT/HvJyclhOQQRERGlPQYWiIgo6YRqiqjsq6DskaAXnOju7sbWrVv9a61fv94fdIiG9N579+4FAPzlL38JCGgQERERpSv2WCAioqQkHdSVDRXV+iq4XK6AHglSGcTNN9+MF198EZMnT/YHJxobG7Fw4UK88cYbcLlcMJlMuP/++6PugyA1hxwyZAjq6urQ2tqKgoICLF68mD0WiIiIKK0xsEBERElJOqgrGypK2QgvvfQSmpqakJ+fj8WLFyMnJwcHDx6E2Wz2Bx6k127duhWzZs0CAP9zxcXFaG1thdvtRlZWVlh70+rfMH/+fABAfn4+XnzxRY6gJCIioozAwAIRESWl4uJi/0FdfpDftm0bBEFATU0N1q5di7Nnz6Kuri6gyaMUeGhpaUFWVhZuv/12f9aA9FxraysA4MYbbwwro8DIJAqtbAsiIiKidMTAAhERJTX5Qb6kpATHjx8HAH8mgNfrRVNTU1DZgVQGsWjRIlRWVvrXk/o3vPjii5gyZQrGjBkT1n6UGRNq5Q5a2RZERERE6YjNG4mIKKnJGzEeP34cdrsdeXl5OHXqFGw2G6655hoAwU0e9bIGpMemTZuG4uLisPcUqrmklG0RydpEREREqYaBBSIiSirKiQ9vvPEGcnJy/Af5qVOnYuHChQCAO+64A8OHDwcQGEBoaGiAzWbD3LlzYbPZgkY+xiKjgOUORERERANYCkFERElD2b+gubkZTqcTn332GbKzswEMNGIcMmQIgIFDvTJIoFxj+/btQT0QiouLUVxcDKvVCgABDRiNYrkDERER0QBBFMVE78GvurparK+vT/Q2iIgogU6dOoWXXnoJ3d3dKCgowIIFC/Dmm2/6sxiGDRuGzs5OuFwufOtb38KoUaNCrvGNb3wjoFyhu7sbq1atCmrAWFtby9GQRERERBoEQdgpimK18nGWQhARUVJR9i8YP368v/QhNzcXra2tyMrKwrJly1SDCmprnDhxIqC8orGx0d+3oampCTabDUuWLFENKihLM5RlFURERESZjqUQRESUdJT9C6R/zpkzBxs2bFBtmKi1Rl9fn+p4yNraWv90CK31jIyWJCIiIsp0zFggIqKko+xfIP2cn58PYCBoECqTQHrN8OHDNbMTQjVglE+kCJXZQERERJSp2GOBiIhSRkdHBxoaGlBVVYXnn38+rB4JjY2NePHFF3H33XejsrIyYL2pU6fqjoZUey0RERFRpmGPBSIiSllSdkJxcTFmzpyJ9vZ2zJs3D1arFU1NTbBarZg3b55uJoFadkJxcTHmz5+vG1TQei0RERERDWCPBSIiSmpafQ5EUYTZbAYA9Pf3Y9OmTbjwwgvR0tKiOjYymvGQHC1JREREpI2lEERElPSU4yNnzpyJ0aNH45VXXkFfXx8AYPjw4Thz5gzHRhIRERHFCUshiIgoZcnHR9bU1GDTpk1YvXo17Ha7/5qTJ0+yuSIRERFRAjCwQEREKUHqb2C32/2TGk6fPg0AuPzyywHA0BhKIiIiIootBhaIiCglyPscyDMYpkyZgoqKCgBsrkhERESUCAwsEBFRSlBOcJCCCNOmTcPIkSMNNVeUpksAQG9vLxoaGuK5ZSIiIqKMwKkQRESUkuQZDFLQQY/WdInKykr2ZCAiIiKKAjMWiIgoJSkzGEIpKCjw92Zoampio0ciIiKiGGFggYiIMoa8NwMbPRIRERHFBgMLRESUUaTeDGz0SERERBQbDCwQEVFGkfdmICIiIqLoMbBAREQZ5ciRI5g5cyY2b96Mw4cP44033vD/U5oUwekRRERERMZxKgQREWUMaTKE2WyGy+XCrl27AMD/zz179sDj8UAURdhsNlRUVKC5uRkul4vTI4iIiIg0MGOBiIgyhjQZIjs7W/X57Oxs3H333TCZTHA6nWhqaoLT6YTJxP9cEhEREWnh35SIiCijyCdDzJgxI+CfN998M8aOHYslS5YgNzcXAJCbm+sfS8kSCSIiIqJgLIUgIqKM0tDQAJvNBgDweDwA4M9IkCZFlJaWYs6cOdiwYQPmzJmD0tJSfxmF1WpFeXk5Wlpa4Ha7WSJBREREGY8ZC0RElDGk4MBrr72GwsJCfPbZZwCAsrKyoEkR+fn5Af+UyihsNhuamppgs9n8mQxEREREmYyBBSIiyhjyHgtdXV3Izc3FAw88gJkzZ2L+/PkoLi72Xzty5EjMnTsXI0eO9D8mL6O4+eabUVpaOtgfgYiIiCjpMLBAREQZQeqPUFpaimuvvRaAfnCguLg4KNgAnC+XkP5JRERElOnYY4GIiNKesj/CyZMnAQB9fX1hr1VUVBRUNkFERESUyZixQEREaU+tP0J1dTWGDx8e9lpamQxEREREmYqBBSIiygjy/ggLFy7EV77yFQYHiIiIiGKAgQUiIsoY7I9AREREFHsMLBARUcZgfwQiIiKi2GPzRiIiyhhSfwQiIiIiih1mLBARERERERFRxBhYICIiIiIiIqKIMbBARERERERERBFjYIGIiJJWQ0MDent7AQC9vb1oaGiI6BoiIiIiih82byQioqTU3d2N119/HTabDRUVFWhubobL5UJlZSUKCgr817z55puwWq0oLy9HS0sL3G53wDVEREREFF/MWCAioqQiz0AQBAFOpxNNTU1wOp0wmQb+syVlJhQUFGDJkiWw2WxoamqCzWbDkiVL/EEFZjMQERERxR8zFoiIKGkoMxBMJhN8Pp//eUEQ8OKLL6K3txdut9ufpXDzzTfjxRdfxM0334zS0lLVtZjNQERERBQfzFggIqKEkzILCgoKcPfdd0MQBDQ1NcHj8fizFEwmEzweD06fPo3+/n4MGzYMzz//PN5880309fUBAPr7+wEMZCc0NjbqZjMQERERUWwwY4GIiAbNgbnz4GltDXisLzsbf7rhBtjsuf7MApfLBQC46aab8Je//AX9/f2w2Wy49tpr8frrryM3NxcnT55EdnY27r77bn/wYe3atRgxYgROnToFl8uFa665RjWbgYiIiIhihxkLREQ0aMxzrsCeUWV4d+IY/2M5Xi9uM5sDMgtuvPFGAEBzczOuuuoqAMBFF12E06dPAwDmzJkDAHC5XFi9ejXeffdd2Gw2+Hw+HDt2DG63G1arFRs3bvRnMwiCMJgflYiIiChjMGOBiIjirrfjDLatW409R/bCV5QH0XT+kC+YTLjwgWXI7unxZxZYrVYIgoAdO3b4AwKffPIJBEHA7NmzkZ+fDwCoqanBhx9+iKamJuTk5GD+/Pl477334PV6Ybfbcd9998FisWDu3LkoKipKxEcnIiIiSnsMLBARUdz4Awqb3gVEH7weDyALKsBqReHChbCUlkKQTYIYNWoUli1bhhdeeME/1cFqteLrX/86xowZg7///e8AgL/+9a8oLi5Gd3c3nE4nSkpK/EvLSx/mz58/SJ+YiIiIKPMwsEBERHHzyqMPo+tUKyCKqs8LJhNKly0FABQVFQVkFpSWlmLhwoV48cUXAQBerxerV6/292EwmUzIyspC67meDTfeeCOGDx+OSy+9FLt372bpAxEREdEgYY8FIiKKmzt//DQuvebLsNhsMFsUsWxB8GcrAEBxcTHmz5+P4uJi2SXngwM33HBDQB+GpUuXYsqUKQCAKVOmoLS0FEeOHMG8efNY+kBEREQ0iBhYICKiuLEXFePqxctw3zO/wyVX1QQEGKwjR/qzFbQUFRVh1qxZmDVrFsaOHYvJkycDGChz8Hq9+PDDDwEAbW1teOmll/Dmm2/CbDYHBSiIiIiIKH4EUSM9NRGqq6vF+vr6RG+DiIjixNHZga3rVuNQ/XZ8+1cvhPXa7u5u/OIXv4DP50N5eTk6OzvhcrlgsVjgcrlQUFCAb3zjGxwpSURERBQngiDsFEWxOuhxBhaIiChVHDp0CH/84x/hdDr9gYSec9Mk7r77blRWViZ6i0RERERpSyuwwFIIIiJKGePGjcOiRYsAnJ/6IPVhYLNGIiIiosRgYIGIiFKKMpCgnCZBRERERIOL4yaJiCilKAMJ0jQJIiIiIkoMBhaIiCilMJBARERElFxYCkFEREREREREEWNggYiIiIiIiIgixsACEREREREREUUs6sCCIAijBEF4TxCEvYIgfCYIQu25x4cIgvCOIAgHzv2zOPrtEhEREREREVEyiUXGggfAQ6IoTgIwG8ADgiBMArAcwLuiKF4I4N1zPxMRERERERFRGok6sCCKYrMoirvO/boHwD4AIwDcBOCFc5e9AODmaN+LiIiIiIiIiJJLTHssCIIwFsA0ANsBDBNFsfncUy0Ahmm85n5BEOoFQag/depULLdDRERERERERHEWs8CCIAh5ANYB+GdRFLvlz4miKAIQ1V4niuL/iKJYLYpidWlpaay2Q0RERERERESDICaBBUEQrBgIKvxBFMVXzz3cKghCxbnnKwC0xeK9iIiIiIiIiCh5xGIqhADgdwD2iaL4c9lTbwC459yv7wHwerTvRURERERERETJxRKDNa4A8A0AnwqC0HDusUcArATwR0EQFgM4AuD2GLwXERERERERESWRqAMLoih+AEDQePpL0a5PRERERERERMkrplMhiIiIiIiIiCizMLBARERERERERBFjYIGIiIiIiIiIIsbAAhERERERERFFjIEFIiIiIiIiIopYLMZNEhERUZo4MHcePK2tQY9bhg3DhX/bNPgbIiIioqTHjAUiIiLyy5s/H7BaAx+0WpF31VWJ2RARERElPQYWiIiIyK9k2VIIpsC/HggmE0qXLU3QjoiIiCjZsRSCiIgow2iVO2gRnU4c+OKVAFgSQURERMGYsUBERJRhVMsdjGBJBBEREalgYIGIiCjDqJU7GMGSCCIiIlLDwAIREVGGsZaVofCWWwBBCONFVhQuXAhLaWn8NkZEREQpiYEFIiKiDFSybKl2OYTFcv6fZjMAZisQERGRNgYWiIiIMpC1rAxFCxcO/CAri7COHQtBCiaYzSi44SuAIDBbgYiIiDRxKgQREVGG6tm4ceAXPp//MXdTE4ScHH8woWTpEvTt3OXPVtCaKMFpEURERJmLgQUiIqIMlX/11ehctw5wu88/aLUi/9oadL/5J3SuXo3O1asBwD9uUsjJGSihULwm76qrGHQgIiLKUCyFICIiylAly5YGBggAwO1G92uvQ7DZgnswWK3Iv/baoIkSUv8F1TGWHFFJRESU9hhYICIiylDWsjLYqqpUntAOIAx76MGBiRJSAEE2LUJtjCWbPhIREaU/BhaIiIgy2PCnngp6LJwAgjxw4B9jqfIaIiIiSl8MLBAREWWwnEkTA7MWwgkgqEyL0HoNERERpS8GFoiIiDKcPGshnACCdeTIoMCB3muIiIgoPQmiKCZ6D37V1dVifX19ordBRESUcZpXPIbOV15Rf9JsxoWb3jMcJHC3teHIXV/H2Jf/wMACERFRGhEEYacoitXKxzlukoiIKMNpjYkEAFitKLrttrACBNayMlS9syFGuyMiIqJkx1IIIiKiDKc6JvIc9kkgIiKiUJixQERElOFKli3VLIMQnU4c+OKVIdewDBuG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\n"},"metadata":{"needs_background":"light"}}]},{"cell_type":"markdown","source":"# Matching","metadata":{}},{"cell_type":"markdown","source":"## Single Beat","metadata":{}},{"cell_type":"code","source":"####### Matching     \n                                                  \n###### Matching File Generartion\n\n##### Data Arrangment                                                                        \n! mkdir './Single_Beat_Ecg_MITBIH_Matching' # Generating major database of datasets\ncurrent_index = 1\n\nmit_dbs_path = '../input/mitbih-database'\nfor i in range(0,96,2): # Loop over all the files\n    rec_file_path = os.path.join(mit_dbs_path,str(np.sort(os.listdir(mit_dbs_path))[i])) # Path Selection\n    attr_file_path = os.path.join(mit_dbs_path,str(np.sort(os.listdir(mit_dbs_path))[i+1])) # Path Selction\n    \n    signal_current = data_read_mit(rec_file_path) # Current ECG Signal\n    r_peaks_current = feature_extractor(attr_file_path) # R-peaks\n    seg_signal_current,new_r_peaks = (segmentSignals(signal_current,list(r_peaks_current))) # Segmented ECG Signals\n    seg_signal_current = np.array(seg_signal_current)_experiment\n    \n    ##### Creation of Person's Folder\n    current_storage_path = './Single_Beat_Ecg_MITBIH_Matching'+'/person'+str(current_index)\n    Path(current_storage_path).mkdir(parents=True, exist_ok=True)\n\n    ##### Creation of Probe and Gallery Subdirectories\n    #### Gallery(Training Set)\n    gallery_path = current_storage_path+'/Gallery'\n    Path(gallery_path).mkdir(parents=True, exist_ok=True)\n\n    #### Probe(Testing Set)\n    probe_path = current_storage_path+'/Probe'\n    Path(probe_path).mkdir(parents=True, exist_ok=True)\n\n    #### Populating Subdirectories\n    for j in range(seg_signal_current.shape[0]):\n\n        if(j%2 == 0):\n            current_output = tsne_model.predict(np.reshape(seg_signal_current[j],(1,256,1)))\n            file_name_current = gallery_path+'/'+str(j)\n            np.savez_compressed(file_name_current,current_output)\n        else:\n            current_output = tsne_model.predict(np.reshape(seg_signal_current[j],(1,256,1)))\n            file_name_current = probe_path+'/'+str(j)\n            np.savez_compressed(file_name_current,current_output)\n\n    current_index = current_index+1","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## 5 Beat Matching","metadata":{}},{"cell_type":"code","source":"###### Extracting Embeddings\n\n##### Model Formation\n\n#### Softmax Model\n#with tpu_strategy.scope():      \ntsne_model = tf.keras.models.Model(inputs=model.input,outputs=model.layers[-2].output)\ntsne_model.compile(tf.keras.optimizers.Adam(lr=1e-4),loss='categorical_crossentropy',metrics=['accuracy'])\ntsne_model.summary()\n\n### ArcFace Model\n#with tpu_strategy.scope():        \ntsne_model = tf.keras.models.Model(inputs=model.input,outputs=model.layers[-3].output)\ntsne_model.compile(tf.keras.optimizers.Adam(lr=1e-4),loss='categorical_crossentropy',metrics=['accuracy'])\ntsne_model.summary()\n\n##### Predicting\n#mat_1 = tsne_model.predict(X_dev)\nmat_1 = tsne_model.predict([X_dev,y_dev_ohot])      \n\n###### Testing and Refining Embeddings\nimport math\nfor i in range(2):\n    print(mat_1[i])\n    \nfor i in range(mat_1.shape[0]):\n    for j in range(mat_1.shape[1]):\n        if(math.isnan(mat_1[i,j])):\n            mat_1[i,j] == 0\n        if(mat_1[i,j]>1e4):\n            mat_1[i,j] == 1e4","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"###### Verification Style Data Arrangment\n! mkdir './5B_Verification'\n! mkdir './5B_Verification/Probe'\n! mkdir './5B_Verification/Gallery'\n\nEnrolment_Ratio = 0.5 # This Signifies the ratio of Enrolment vs Evaluation\n\nfor i in range(48): # Looping over all the Dev Set Examples\n\n    ##### Creation of SubFolders\n    current_folder_gallery = './5B_Verification/Gallery/Person'+str(i)\n    current_folder_probe = './5B_Verification/Probe/Person'+str(i)\n\n    Path(current_folder_gallery).mkdir(parents=True, exist_ok=True)\n    Path(current_folder_probe).mkdir(parents=True, exist_ok=True)\n\n    ##### Curating List of Examples belonging to Class 'i'\n    item_index = []\n    for j in range(X_dev.shape[0]):\n        if(y_dev[j] == i):\n            item_index.append(j)\n            \n    ##### Probe and Gallery Divison\n    #divison_range = int(len(item_index)*Enrolment_Ratio)\n\n    #### Gallery Appendment\n    #for a in range(divison_range):\n    #    path_curr = current_folder_gallery+'/'+str(a)\n    #    np.savez_compressed(path_curr,mat_1[int(item_index[a])])\n\n    #### Probe Appendment\n    #for b in range(divison_range,len(item_index)):\n    #    path_curr = current_folder_probe+'/'+str(b-divison_range)\n    #    np.savez_compressed(path_curr,mat_1[int(item_index[b])])\n\n    print('Data Arranged for Person '+str(i)) # Declaration of Data Arrangment for the 'i'th Person","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"Matching_Matrix = [] # For Appending the Scores onto a List\nmatch_text = open(\"./5B_Matching_50_50_Final.txt\",'w') # Matching Text File Creation\n\nprobe_path = './5B_Verification/Probe'\ngallery_path = './5B_Verification/Gallery'\n\nfor probe_person_id,probe_person in enumerate(list(np.sort(os.listdir(probe_path)))): #Loop over the Probe Folder\n    probe_person_path = os.path.join(probe_path,probe_person)\n\n    print('Processing For User Probe '+str(probe_person_id))\n\n    for probe_id,probe_file in enumerate(list(np.sort(os.listdir(probe_person_path)))): #Loop over the Probe Person\n        probe_file_path = os.path.join(probe_person_path,probe_file)\n        probe = np.load(probe_file_path,allow_pickle='True')['arr_0'] # Current Probe\n\n        for gallery_person_id,gallery_person in enumerate(list(np.sort(os.listdir(gallery_path)))): #Loop over the Galleryy Folder\n            gallery_person_path = os.path.join(gallery_path,gallery_person)\n            \n            #print('Processing For User Gallery '+str(gallery_person_id)+' and User Probe '+str(probe_person_id))\n\n            for gallery_id,gallery_file in enumerate(list(np.sort(os.listdir(gallery_person_path)))):\n                gallery_file_path = os.path.join(gallery_person_path,gallery_file)\n                gallery = np.load(gallery_file_path,allow_pickle='True')['arr_0'] # Current Gallery\n\n                if(probe_person_id <= 17 and gallery_person_id <=17): # Doing Analysis over 18 subjects\n                \n                    ##### Metrics Computation\n                    #if(subject_probe_id != subject_gallery_id and probe_id != gallery_id):\n                    distance = (np.linalg.norm(probe-gallery)) #Euclidean Distance between Probe and Gallery\n                    #print(distance)\n                    if(probe_person_id == gallery_person_id):\n                        identity_flag = 1\n                    else:\n                        identity_flag = 0\n                    current_matching_matrix = [probe_person_id+1,probe_id+1,gallery_person_id+1,gallery_id+1,identity_flag,distance]\n\n                    ### For Array Appending       \n                    #Matching_Matrix.append(current_mathing_matrix)   \n\n                    ### For Text File Appending\n                    for item_idx,item in enumerate(current_matching_matrix):   \n                        if(item_idx <= 4):                  \n                            match_text.write(str(item)+'            ')                  \n                        else:                                    \n                            match_text.write(str(item)+\"\\n\")   \n                else:\n                    break ","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"###### Matching File Generation\nMatching_Matrix = [] # For Appending the Scores onto a List\nmatch_text = open(\"./OSV_50-50_Test-2.txt\",'w') # Matching Text File Creation   \nnum_probe_samples = 24 # Number of Subjects to be considered in Probe            \nnum_gallery_samples = 24 # Number of Subjects to be considered in Gallery                     \n\n##### Probe Selection\nfor probe_class in range(num_probe_samples): # Looping over Probe Examples\n    \n    print('Currently Processing for Probe Class '+str(probe_class))\n\n    #### Curating List of Examples belonging to Class 'probe_class'\n    item_index = []\n    for j in range(X_dev.shape[0]):\n        if(y_dev[j] == probe_class):\n            item_index.append(j)   \n\n    for probe_id,probe_loc in enumerate(item_index):\n        probe = Test_Embeddings[probe_loc] # Probe Selection \n\n        ##### Gallery Selection\n        for gallery_class in range(num_gallery_samples): # Looping over Gallery Examples\n\n            #print('Currently Processing for Gallery Class '+str(gallery_class))\n\n            #### Curating List of Examples belonging to Class 'probe_class'\n            item_index = []\n            for j in range(X_train.shape[0]):\n                if(y_train[j] == gallery_class):\n                    item_index.append(j)   \n\n            for gallery_id,gallery_loc in enumerate(item_index):\n                gallery = Train_Embeddings[gallery_loc] # Probe Selection \n\n                #### Metrics Computation \n                cos_distance = distance.cosine(probe,gallery) # Cosine Distance between Probe and Gallery\n                \n                if(probe_class == gallery_class): # Identity Flag\n                    identity_flag = 1\n                else:\n                    identity_flag = 0\n                current_matching_matrix = [probe_class+1,probe_id+1,gallery_class+1,gallery_id+1,identity_flag,cos_distance]\n                \n                ### For Array Appending       \n                #Matching_Matrix.append(current_mathing_matrix)\n\n                ### For Text File Appending\n                for item_idx,item in enumerate(current_matching_matrix):\n                    if(item_idx <= 4):\n                        match_text.write(str(item)+'            ')\n                    else:            \n                        match_text.write(str(item)+\"\\n\")","metadata":{"trusted":true},"execution_count":null,"outputs":[]}]}